- (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:
parent
559d383037
commit
0bc1bd814e
33
ChangeLog
33
ChangeLog
|
@ -1,6 +1,39 @@
|
|||
20001113
|
||||
- (djm) Add pointer to http://www.imasy.or.jp/~gotoh/connect.c to
|
||||
contrib/README
|
||||
- (djm) Merge OpenBSD changes:
|
||||
- markus@cvs.openbsd.org 2000/11/06 16:04:56
|
||||
[channels.c channels.h clientloop.c nchan.c serverloop.c]
|
||||
[session.c ssh.c]
|
||||
agent forwarding and -R for ssh2, based on work from
|
||||
jhuuskon@messi.uku.fi
|
||||
- markus@cvs.openbsd.org 2000/11/06 16:13:27
|
||||
[ssh.c sshconnect.c sshd.c]
|
||||
do not disabled rhosts(rsa) if server port > 1024; from
|
||||
pekkas@netcore.fi
|
||||
- markus@cvs.openbsd.org 2000/11/06 16:16:35
|
||||
[sshconnect.c]
|
||||
downgrade client to 1.3 if server is 1.4; help from mdb@juniper.net
|
||||
- markus@cvs.openbsd.org 2000/11/09 18:04:40
|
||||
[auth1.c]
|
||||
typo; from mouring@pconline.com
|
||||
- markus@cvs.openbsd.org 2000/11/12 12:03:28
|
||||
[ssh-agent.c]
|
||||
off-by-one when removing a key from the agent
|
||||
- markus@cvs.openbsd.org 2000/11/12 12:50:39
|
||||
[auth-rh-rsa.c auth2.c authfd.c authfd.h]
|
||||
[authfile.c hostfile.c kex.c kex.h key.c key.h myproposal.h]
|
||||
[readconf.c readconf.h rsa.c rsa.h servconf.c servconf.h ssh-add.c]
|
||||
[ssh-agent.c ssh-keygen.1 ssh-keygen.c ssh.1 ssh.c ssh_config]
|
||||
[sshconnect1.c sshconnect2.c sshd.8 sshd.c sshd_config ssh-dss.c]
|
||||
[ssh-dss.h ssh-rsa.c ssh-rsa.h dsa.c dsa.h]
|
||||
add support for RSA to SSH2. please test.
|
||||
there are now 3 types of keys: RSA1 is used by ssh-1 only,
|
||||
RSA and DSA are used by SSH2.
|
||||
you can use 'ssh-keygen -t rsa -f ssh2_rsa_file' to generate RSA
|
||||
keys for SSH2 and use the RSA keys for hostkeys or for user keys.
|
||||
SSH2 RSA or DSA keys are added to .ssh/authorised_keys2 as before.
|
||||
- (djm) Fix up Makefile and Redhat init script to create RSA host keys
|
||||
|
||||
20001112
|
||||
- (bal) SCO Patch to add needed libraries for configure.in. Patch by
|
||||
|
|
16
Makefile.in
16
Makefile.in
|
@ -35,7 +35,7 @@ INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
|
|||
|
||||
TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) $(EXTRA_TARGETS)
|
||||
|
||||
LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o cli.o compat.o compress.o crc32.o cygwin_util.o deattack.o dispatch.o dsa.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o util.o uuencode.o xmalloc.o
|
||||
LIBSSH_OBJS=atomicio.o authfd.o authfile.o bufaux.o buffer.o canohost.o channels.o cipher.o cli.o compat.o compress.o crc32.o cygwin_util.o deattack.o dispatch.o hmac.o hostfile.o key.o kex.o log.o match.o mpaux.o nchan.o packet.o radix.o rijndael.o entropy.o readpass.o rsa.o ssh-dss.o ssh-rsa.o tildexpand.o ttymodes.o uidswap.o util.o uuencode.o xmalloc.o
|
||||
|
||||
LIBOPENBSD_COMPAT_OBJS=bsd-arc4random.o bsd-base64.o bsd-bindresvport.o bsd-daemon.o bsd-getcwd.o bsd-inet_aton.o bsd-inet_ntoa.o bsd-misc.o bsd-mktemp.o bsd-realpath.o bsd-rresvport.o bsd-setenv.o bsd-sigaction.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bsd-strsep.o bsd-strtok.o bsd-vis.o bsd-setproctitle.o bsd-waitpid.o fake-getaddrinfo.o fake-getnameinfo.o next-posix.o
|
||||
|
||||
|
@ -179,18 +179,24 @@ host-key: ssh-keygen$(EXEEXT)
|
|||
if [ -f "$(DESTDIR)$(sysconfdir)/ssh_host_key" ] ; then \
|
||||
echo "$(DESTDIR)$(sysconfdir)/ssh_host_key already exists, skipping." ; \
|
||||
else \
|
||||
$(srcdir)/ssh-keygen -b 1024 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N "" ; \
|
||||
$(srcdir)/ssh-keygen -t rsa1 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N "" ; \
|
||||
fi ; \
|
||||
if [ -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key ] ; then \
|
||||
echo "$(DESTDIR)$(sysconfdir)/ssh_host_dsa_key already exists, skipping." ; \
|
||||
else \
|
||||
$(srcdir)/ssh-keygen -d -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N "" ; \
|
||||
$(srcdir)/ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N "" ; \
|
||||
fi ; \
|
||||
if [ -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key ] ; then \
|
||||
echo "$(DESTDIR)$(sysconfdir)/ssh_host_rsa_key already exists, skipping." ; \
|
||||
else \
|
||||
$(srcdir)/ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N "" ; \
|
||||
fi ; \
|
||||
fi ;
|
||||
|
||||
host-key-force: ssh-keygen$(EXEEXT)
|
||||
$(srcdir)/ssh-keygen -b 1024 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N ""
|
||||
$(srcdir)/ssh-keygen -d -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N ""
|
||||
$(srcdir)/ssh-keygen -t rsa1 -f $(DESTDIR)$(sysconfdir)/ssh_host_key -N ""
|
||||
$(srcdir)/ssh-keygen -t dsa -f $(DESTDIR)$(sysconfdir)/ssh_host_dsa_key -N ""
|
||||
$(srcdir)/ssh-keygen -t rsa -f $(DESTDIR)$(sysconfdir)/ssh_host_rsa_key -N ""
|
||||
|
||||
uninstallall: uninstall
|
||||
-rm -f $(DESTDIR)$(sysconfdir)/ssh_config
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: auth-rh-rsa.c,v 1.17 2000/10/03 18:03:03 markus Exp $");
|
||||
RCSID("$OpenBSD: auth-rh-rsa.c,v 1.18 2000/11/12 19:50:37 markus Exp $");
|
||||
|
||||
#include "packet.h"
|
||||
#include "ssh.h"
|
||||
|
@ -53,10 +53,10 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user, RSA *client_host_key
|
|||
debug("Rhosts RSA authentication: canonical host %.900s", canonical_hostname);
|
||||
|
||||
/* wrap the RSA key into a 'generic' key */
|
||||
client_key = key_new(KEY_RSA);
|
||||
client_key = key_new(KEY_RSA1);
|
||||
BN_copy(client_key->rsa->e, client_host_key->e);
|
||||
BN_copy(client_key->rsa->n, client_host_key->n);
|
||||
found = key_new(KEY_RSA);
|
||||
found = key_new(KEY_RSA1);
|
||||
|
||||
/* Check if we know the host and its host key. */
|
||||
host_status = check_host_in_hostfile(SSH_SYSTEM_HOSTFILE, canonical_hostname,
|
||||
|
|
2
auth1.c
2
auth1.c
|
@ -10,7 +10,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: auth1.c,v 1.6 2000/10/11 20:27:23 markus Exp $");
|
||||
RCSID("$OpenBSD: auth1.c,v 1.7 2000/11/10 01:04:40 markus Exp $");
|
||||
|
||||
#ifdef HAVE_OSF_SIA
|
||||
# include <sia.h>
|
||||
|
|
38
auth2.c
38
auth2.c
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: auth2.c,v 1.20 2000/10/14 12:16:56 markus Exp $");
|
||||
RCSID("$OpenBSD: auth2.c,v 1.21 2000/11/12 19:50:37 markus Exp $");
|
||||
|
||||
#ifdef HAVE_OSF_SIA
|
||||
# include <sia.h>
|
||||
|
@ -52,7 +52,6 @@ RCSID("$OpenBSD: auth2.c,v 1.20 2000/10/14 12:16:56 markus Exp $");
|
|||
#include "key.h"
|
||||
#include "kex.h"
|
||||
|
||||
#include "dsa.h"
|
||||
#include "uidswap.h"
|
||||
#include "auth-options.h"
|
||||
|
||||
|
@ -89,7 +88,7 @@ void protocol_error(int type, int plen, void *ctxt);
|
|||
/* helper */
|
||||
Authmethod *authmethod_lookup(const char *name);
|
||||
struct passwd *pwcopy(struct passwd *pw);
|
||||
int user_dsa_key_allowed(struct passwd *pw, Key *key);
|
||||
int user_key_allowed(struct passwd *pw, Key *key);
|
||||
char *authmethods_get(void);
|
||||
|
||||
/* auth */
|
||||
|
@ -104,7 +103,7 @@ Authmethod authmethods[] = {
|
|||
&one},
|
||||
{"publickey",
|
||||
userauth_pubkey,
|
||||
&options.dsa_authentication},
|
||||
&options.pubkey_authentication},
|
||||
{"keyboard-interactive",
|
||||
userauth_kbdint,
|
||||
&options.kbd_interactive_authentication},
|
||||
|
@ -422,7 +421,7 @@ userauth_pubkey(Authctxt *authctxt)
|
|||
Key *key;
|
||||
char *pkalg, *pkblob, *sig;
|
||||
unsigned int alen, blen, slen;
|
||||
int have_sig;
|
||||
int have_sig, pktype;
|
||||
int authenticated = 0;
|
||||
|
||||
if (!authctxt->valid) {
|
||||
|
@ -431,13 +430,14 @@ userauth_pubkey(Authctxt *authctxt)
|
|||
}
|
||||
have_sig = packet_get_char();
|
||||
pkalg = packet_get_string(&alen);
|
||||
if (strcmp(pkalg, KEX_DSS) != 0) {
|
||||
log("bad pkalg %s", pkalg); /*XXX*/
|
||||
pktype = key_type_from_name(pkalg);
|
||||
if (pktype == KEY_UNSPEC) {
|
||||
log("bad pkalg %s", pkalg);
|
||||
xfree(pkalg);
|
||||
return 0;
|
||||
}
|
||||
pkblob = packet_get_string(&blen);
|
||||
key = dsa_key_from_blob(pkblob, blen);
|
||||
key = key_from_blob(pkblob, blen);
|
||||
if (key != NULL) {
|
||||
if (have_sig) {
|
||||
sig = packet_get_string(&slen);
|
||||
|
@ -457,14 +457,14 @@ userauth_pubkey(Authctxt *authctxt)
|
|||
authctxt->service);
|
||||
buffer_put_cstring(&b, "publickey");
|
||||
buffer_put_char(&b, have_sig);
|
||||
buffer_put_cstring(&b, KEX_DSS);
|
||||
buffer_put_cstring(&b, key_ssh_name(key));
|
||||
buffer_put_string(&b, pkblob, blen);
|
||||
#ifdef DEBUG_DSS
|
||||
#ifdef DEBUG_PK
|
||||
buffer_dump(&b);
|
||||
#endif
|
||||
/* test for correct signature */
|
||||
if (user_dsa_key_allowed(authctxt->pw, key) &&
|
||||
dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
|
||||
if (user_key_allowed(authctxt->pw, key) &&
|
||||
key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
|
||||
authenticated = 1;
|
||||
buffer_clear(&b);
|
||||
xfree(sig);
|
||||
|
@ -480,7 +480,7 @@ userauth_pubkey(Authctxt *authctxt)
|
|||
* if a user is not allowed to login. is this an
|
||||
* issue? -markus
|
||||
*/
|
||||
if (user_dsa_key_allowed(authctxt->pw, key)) {
|
||||
if (user_key_allowed(authctxt->pw, key)) {
|
||||
packet_start(SSH2_MSG_USERAUTH_PK_OK);
|
||||
packet_put_string(pkalg, alen);
|
||||
packet_put_string(pkblob, blen);
|
||||
|
@ -493,6 +493,7 @@ userauth_pubkey(Authctxt *authctxt)
|
|||
auth_clear_options();
|
||||
key_free(key);
|
||||
}
|
||||
debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
|
||||
xfree(pkalg);
|
||||
xfree(pkblob);
|
||||
#ifdef HAVE_CYGWIN
|
||||
|
@ -560,11 +561,10 @@ authmethod_lookup(const char *name)
|
|||
|
||||
/* return 1 if user allows given key */
|
||||
int
|
||||
user_dsa_key_allowed(struct passwd *pw, Key *key)
|
||||
user_key_allowed(struct passwd *pw, Key *key)
|
||||
{
|
||||
char line[8192], file[1024];
|
||||
int found_key = 0;
|
||||
unsigned int bits = -1;
|
||||
FILE *f;
|
||||
unsigned long linenum = 0;
|
||||
struct stat st;
|
||||
|
@ -645,10 +645,10 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
|
|||
if (!*cp || *cp == '\n' || *cp == '#')
|
||||
continue;
|
||||
|
||||
bits = key_read(found, &cp);
|
||||
if (bits == 0) {
|
||||
if (key_read(found, &cp) == -1) {
|
||||
/* no key? check if there are options for this key */
|
||||
int quoted = 0;
|
||||
debug2("user_key_allowed: check options: '%s'", cp);
|
||||
options = cp;
|
||||
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
|
||||
if (*cp == '\\' && cp[1] == '"')
|
||||
|
@ -659,8 +659,8 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
|
|||
/* Skip remaining whitespace. */
|
||||
for (; *cp == ' ' || *cp == '\t'; cp++)
|
||||
;
|
||||
bits = key_read(found, &cp);
|
||||
if (bits == 0) {
|
||||
if (key_read(found, &cp) == -1) {
|
||||
debug2("user_key_allowed: advance: '%s'", cp);
|
||||
/* still no key? advance to next line*/
|
||||
continue;
|
||||
}
|
||||
|
|
76
authfd.c
76
authfd.c
|
@ -35,7 +35,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: authfd.c,v 1.29 2000/10/09 21:51:00 markus Exp $");
|
||||
RCSID("$OpenBSD: authfd.c,v 1.30 2000/11/12 19:50:37 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "rsa.h"
|
||||
|
@ -50,7 +50,6 @@ RCSID("$OpenBSD: authfd.c,v 1.29 2000/10/09 21:51:00 markus Exp $");
|
|||
#include "key.h"
|
||||
#include "authfd.h"
|
||||
#include "kex.h"
|
||||
#include "dsa.h"
|
||||
#include "compat.h"
|
||||
|
||||
/* helper */
|
||||
|
@ -211,8 +210,8 @@ ssh_close_authentication_connection(AuthenticationConnection *auth)
|
|||
* Returns the first authentication identity held by the agent.
|
||||
*/
|
||||
|
||||
Key *
|
||||
ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version)
|
||||
int
|
||||
ssh_get_num_identities(AuthenticationConnection *auth, int version)
|
||||
{
|
||||
int type, code1 = 0, code2 = 0;
|
||||
Buffer request;
|
||||
|
@ -227,7 +226,7 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi
|
|||
code2 = SSH2_AGENT_IDENTITIES_ANSWER;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -240,14 +239,14 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi
|
|||
buffer_clear(&auth->identities);
|
||||
if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
|
||||
buffer_free(&request);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
buffer_free(&request);
|
||||
|
||||
/* Get message type, and verify that we got a proper answer. */
|
||||
type = buffer_get_char(&auth->identities);
|
||||
if (agent_failed(type)) {
|
||||
return NULL;
|
||||
return 0;
|
||||
} else if (type != code2) {
|
||||
fatal("Bad authentication reply message type: %d", type);
|
||||
}
|
||||
|
@ -258,8 +257,16 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi
|
|||
fatal("Too many identities in authentication reply: %d\n",
|
||||
auth->howmany);
|
||||
|
||||
/* Return the first entry (if any). */
|
||||
return ssh_get_next_identity(auth, comment, version);
|
||||
return auth->howmany;
|
||||
}
|
||||
|
||||
Key *
|
||||
ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version)
|
||||
{
|
||||
/* get number of identities and return the first entry (if any). */
|
||||
if (ssh_get_num_identities(auth, version) > 0)
|
||||
return ssh_get_next_identity(auth, comment, version);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Key *
|
||||
|
@ -280,7 +287,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio
|
|||
*/
|
||||
switch(version){
|
||||
case 1:
|
||||
key = key_new(KEY_RSA);
|
||||
key = key_new(KEY_RSA1);
|
||||
bits = buffer_get_int(&auth->identities);
|
||||
buffer_get_bignum(&auth->identities, key->rsa->e);
|
||||
buffer_get_bignum(&auth->identities, key->rsa->n);
|
||||
|
@ -292,7 +299,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio
|
|||
case 2:
|
||||
blob = buffer_get_string(&auth->identities, &blen);
|
||||
*comment = buffer_get_string(&auth->identities, NULL);
|
||||
key = dsa_key_from_blob(blob, blen);
|
||||
key = key_from_blob(blob, blen);
|
||||
xfree(blob);
|
||||
break;
|
||||
default:
|
||||
|
@ -324,7 +331,7 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
|
|||
int i;
|
||||
int type;
|
||||
|
||||
if (key->type != KEY_RSA)
|
||||
if (key->type != KEY_RSA1)
|
||||
return 0;
|
||||
if (response_type == 0) {
|
||||
log("Compatibility with ssh protocol version 1.0 no longer supported.");
|
||||
|
@ -376,7 +383,7 @@ ssh_agent_sign(AuthenticationConnection *auth,
|
|||
int type, flags = 0;
|
||||
int ret = -1;
|
||||
|
||||
if (dsa_make_key_blob(key, &blob, &blen) == 0)
|
||||
if (key_to_blob(key, &blob, &blen) == 0)
|
||||
return -1;
|
||||
|
||||
if (datafellows & SSH_BUG_SIGBLOB)
|
||||
|
@ -409,7 +416,7 @@ ssh_agent_sign(AuthenticationConnection *auth,
|
|||
/* Encode key for a message to the agent. */
|
||||
|
||||
void
|
||||
ssh_encode_identity_rsa(Buffer *b, RSA *key, const char *comment)
|
||||
ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
|
||||
{
|
||||
buffer_clear(b);
|
||||
buffer_put_char(b, SSH_AGENTC_ADD_RSA_IDENTITY);
|
||||
|
@ -425,17 +432,29 @@ ssh_encode_identity_rsa(Buffer *b, RSA *key, const char *comment)
|
|||
}
|
||||
|
||||
void
|
||||
ssh_encode_identity_dsa(Buffer *b, DSA *key, const char *comment)
|
||||
ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
|
||||
{
|
||||
buffer_clear(b);
|
||||
buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY);
|
||||
buffer_put_cstring(b, KEX_DSS);
|
||||
buffer_put_bignum2(b, key->p);
|
||||
buffer_put_bignum2(b, key->q);
|
||||
buffer_put_bignum2(b, key->g);
|
||||
buffer_put_bignum2(b, key->pub_key);
|
||||
buffer_put_bignum2(b, key->priv_key);
|
||||
buffer_put_string(b, comment, strlen(comment));
|
||||
buffer_put_cstring(b, key_ssh_name(key));
|
||||
switch(key->type){
|
||||
case KEY_RSA:
|
||||
buffer_put_bignum2(b, key->rsa->n);
|
||||
buffer_put_bignum2(b, key->rsa->e);
|
||||
buffer_put_bignum2(b, key->rsa->d);
|
||||
buffer_put_bignum2(b, key->rsa->iqmp);
|
||||
buffer_put_bignum2(b, key->rsa->p);
|
||||
buffer_put_bignum2(b, key->rsa->q);
|
||||
break;
|
||||
case KEY_DSA:
|
||||
buffer_put_bignum2(b, key->dsa->p);
|
||||
buffer_put_bignum2(b, key->dsa->q);
|
||||
buffer_put_bignum2(b, key->dsa->g);
|
||||
buffer_put_bignum2(b, key->dsa->pub_key);
|
||||
buffer_put_bignum2(b, key->dsa->priv_key);
|
||||
break;
|
||||
}
|
||||
buffer_put_cstring(b, comment);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -452,11 +471,12 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
|
|||
buffer_init(&msg);
|
||||
|
||||
switch (key->type) {
|
||||
case KEY_RSA:
|
||||
ssh_encode_identity_rsa(&msg, key->rsa, comment);
|
||||
case KEY_RSA1:
|
||||
ssh_encode_identity_rsa1(&msg, key->rsa, comment);
|
||||
break;
|
||||
case KEY_RSA:
|
||||
case KEY_DSA:
|
||||
ssh_encode_identity_dsa(&msg, key->dsa, comment);
|
||||
ssh_encode_identity_ssh2(&msg, key, comment);
|
||||
break;
|
||||
default:
|
||||
buffer_free(&msg);
|
||||
|
@ -487,13 +507,13 @@ ssh_remove_identity(AuthenticationConnection *auth, Key *key)
|
|||
|
||||
buffer_init(&msg);
|
||||
|
||||
if (key->type == KEY_RSA) {
|
||||
if (key->type == KEY_RSA1) {
|
||||
buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY);
|
||||
buffer_put_int(&msg, BN_num_bits(key->rsa->n));
|
||||
buffer_put_bignum(&msg, key->rsa->e);
|
||||
buffer_put_bignum(&msg, key->rsa->n);
|
||||
} else if (key->type == KEY_DSA) {
|
||||
dsa_make_key_blob(key, &blob, &blen);
|
||||
} else if (key->type == KEY_DSA || key->type == KEY_RSA) {
|
||||
key_to_blob(key, &blob, &blen);
|
||||
buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
|
||||
buffer_put_string(&msg, blob, blen);
|
||||
xfree(blob);
|
||||
|
|
7
authfd.h
7
authfd.h
|
@ -11,7 +11,7 @@
|
|||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*/
|
||||
|
||||
/* RCSID("$OpenBSD: authfd.h,v 1.13 2000/10/09 21:51:00 markus Exp $"); */
|
||||
/* RCSID("$OpenBSD: authfd.h,v 1.14 2000/11/12 19:50:37 markus Exp $"); */
|
||||
|
||||
#ifndef AUTHFD_H
|
||||
#define AUTHFD_H
|
||||
|
@ -74,6 +74,11 @@ AuthenticationConnection *ssh_get_authentication_connection();
|
|||
*/
|
||||
void ssh_close_authentication_connection(AuthenticationConnection *auth);
|
||||
|
||||
/*
|
||||
* Returns the number authentication identity held by the agent.
|
||||
*/
|
||||
int ssh_get_num_identities(AuthenticationConnection *auth, int version);
|
||||
|
||||
/*
|
||||
* Returns the first authentication identity held by the agent or NULL if
|
||||
* no identies are available. Caller must free comment and key.
|
||||
|
|
140
authfile.c
140
authfile.c
|
@ -36,11 +36,12 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: authfile.c,v 1.20 2000/10/11 20:27:23 markus Exp $");
|
||||
RCSID("$OpenBSD: authfile.c,v 1.21 2000/11/12 19:50:37 markus Exp $");
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
|
@ -61,7 +62,7 @@ RCSID("$OpenBSD: authfile.c,v 1.20 2000/10/11 20:27:23 markus Exp $");
|
|||
*/
|
||||
|
||||
int
|
||||
save_private_key_rsa(const char *filename, const char *passphrase,
|
||||
save_private_key_rsa1(const char *filename, const char *passphrase,
|
||||
RSA *key, const char *comment)
|
||||
{
|
||||
Buffer buffer, encrypted;
|
||||
|
@ -155,16 +156,17 @@ save_private_key_rsa(const char *filename, const char *passphrase,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* save DSA key in OpenSSL PEM format */
|
||||
|
||||
/* save SSH2 key in OpenSSL PEM format */
|
||||
int
|
||||
save_private_key_dsa(const char *filename, const char *passphrase,
|
||||
DSA *dsa, const char *comment)
|
||||
save_private_key_ssh2(const char *filename, const char *_passphrase,
|
||||
Key *key, const char *comment)
|
||||
{
|
||||
FILE *fp;
|
||||
int fd;
|
||||
int success = 1;
|
||||
int len = strlen(passphrase);
|
||||
int success = 0;
|
||||
int len = strlen(_passphrase);
|
||||
char *passphrase = (len > 0) ? (char *)_passphrase : NULL;
|
||||
EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
|
||||
|
||||
if (len > 0 && len <= 4) {
|
||||
error("passphrase too short: %d bytes", len);
|
||||
|
@ -182,14 +184,15 @@ save_private_key_dsa(const char *filename, const char *passphrase,
|
|||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
if (len > 0) {
|
||||
if (!PEM_write_DSAPrivateKey(fp, dsa, EVP_des_ede3_cbc(),
|
||||
(char *)passphrase, strlen(passphrase), NULL, NULL))
|
||||
success = 0;
|
||||
} else {
|
||||
if (!PEM_write_DSAPrivateKey(fp, dsa, NULL,
|
||||
NULL, 0, NULL, NULL))
|
||||
success = 0;
|
||||
switch (key->type) {
|
||||
case KEY_DSA:
|
||||
success = PEM_write_DSAPrivateKey(fp, key->dsa,
|
||||
cipher, passphrase, len, NULL, NULL);
|
||||
break;
|
||||
case KEY_RSA:
|
||||
success = PEM_write_RSAPrivateKey(fp, key->rsa,
|
||||
cipher, passphrase, len, NULL, NULL);
|
||||
break;
|
||||
}
|
||||
fclose(fp);
|
||||
return success;
|
||||
|
@ -200,11 +203,12 @@ save_private_key(const char *filename, const char *passphrase, Key *key,
|
|||
const char *comment)
|
||||
{
|
||||
switch (key->type) {
|
||||
case KEY_RSA:
|
||||
return save_private_key_rsa(filename, passphrase, key->rsa, comment);
|
||||
case KEY_RSA1:
|
||||
return save_private_key_rsa1(filename, passphrase, key->rsa, comment);
|
||||
break;
|
||||
case KEY_DSA:
|
||||
return save_private_key_dsa(filename, passphrase, key->dsa, comment);
|
||||
case KEY_RSA:
|
||||
return save_private_key_ssh2(filename, passphrase, key, comment);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -246,7 +250,7 @@ load_public_key_rsa(const char *filename, RSA * pub, char **comment_return)
|
|||
|
||||
/* Check that it is at least big enought to contain the ID string. */
|
||||
if (len < strlen(AUTHFILE_ID_STRING) + 1) {
|
||||
debug("Bad key file %.200s.", filename);
|
||||
debug3("Bad RSA1 key file %.200s.", filename);
|
||||
buffer_free(&buffer);
|
||||
return 0;
|
||||
}
|
||||
|
@ -256,7 +260,7 @@ load_public_key_rsa(const char *filename, RSA * pub, char **comment_return)
|
|||
*/
|
||||
for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)
|
||||
if (buffer_get_char(&buffer) != (u_char) AUTHFILE_ID_STRING[i]) {
|
||||
debug("Bad key file %.200s.", filename);
|
||||
debug3("Bad RSA1 key file %.200s.", filename);
|
||||
buffer_free(&buffer);
|
||||
return 0;
|
||||
}
|
||||
|
@ -288,10 +292,11 @@ int
|
|||
load_public_key(const char *filename, Key * key, char **comment_return)
|
||||
{
|
||||
switch (key->type) {
|
||||
case KEY_RSA:
|
||||
case KEY_RSA1:
|
||||
return load_public_key_rsa(filename, key->rsa, comment_return);
|
||||
break;
|
||||
case KEY_DSA:
|
||||
case KEY_RSA:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -306,7 +311,7 @@ load_public_key(const char *filename, Key * key, char **comment_return)
|
|||
*/
|
||||
|
||||
int
|
||||
load_private_key_rsa(int fd, const char *filename,
|
||||
load_private_key_rsa1(int fd, const char *filename,
|
||||
const char *passphrase, RSA * prv, char **comment_return)
|
||||
{
|
||||
int i, check1, check2, cipher_type;
|
||||
|
@ -326,7 +331,7 @@ load_private_key_rsa(int fd, const char *filename,
|
|||
|
||||
if (read(fd, cp, (size_t) len) != (size_t) len) {
|
||||
debug("Read from key file %.200s failed: %.100s", filename,
|
||||
strerror(errno));
|
||||
strerror(errno));
|
||||
buffer_free(&buffer);
|
||||
close(fd);
|
||||
return 0;
|
||||
|
@ -335,7 +340,7 @@ load_private_key_rsa(int fd, const char *filename,
|
|||
|
||||
/* Check that it is at least big enought to contain the ID string. */
|
||||
if (len < strlen(AUTHFILE_ID_STRING) + 1) {
|
||||
debug("Bad key file %.200s.", filename);
|
||||
debug3("Bad RSA1 key file %.200s.", filename);
|
||||
buffer_free(&buffer);
|
||||
return 0;
|
||||
}
|
||||
|
@ -344,8 +349,8 @@ load_private_key_rsa(int fd, const char *filename,
|
|||
* from the buffer.
|
||||
*/
|
||||
for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)
|
||||
if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) {
|
||||
debug("Bad key file %.200s.", filename);
|
||||
if (buffer_get_char(&buffer) != (u_char) AUTHFILE_ID_STRING[i]) {
|
||||
debug3("Bad RSA1 key file %.200s.", filename);
|
||||
buffer_free(&buffer);
|
||||
return 0;
|
||||
}
|
||||
|
@ -431,40 +436,59 @@ fail:
|
|||
}
|
||||
|
||||
int
|
||||
load_private_key_dsa(int fd, const char *passphrase, Key *k, char **comment_return)
|
||||
load_private_key_ssh2(int fd, const char *passphrase, Key *k, char **comment_return)
|
||||
{
|
||||
DSA *dsa;
|
||||
BIO *in;
|
||||
FILE *fp;
|
||||
int success = 0;
|
||||
EVP_PKEY *pk = NULL;
|
||||
char *name = "<no key>";
|
||||
|
||||
in = BIO_new(BIO_s_file());
|
||||
if (in == NULL) {
|
||||
error("BIO_new failed");
|
||||
return 0;
|
||||
}
|
||||
fp = fdopen(fd, "r");
|
||||
if (fp == NULL) {
|
||||
error("fdopen failed");
|
||||
return 0;
|
||||
}
|
||||
BIO_set_fp(in, fp, BIO_NOCLOSE);
|
||||
dsa = PEM_read_bio_DSAPrivateKey(in, NULL, NULL, (char *)passphrase);
|
||||
if (dsa == NULL) {
|
||||
debug("PEM_read_bio_DSAPrivateKey failed");
|
||||
} else {
|
||||
/* replace k->dsa with loaded key */
|
||||
DSA_free(k->dsa);
|
||||
k->dsa = dsa;
|
||||
}
|
||||
BIO_free(in);
|
||||
fclose(fp);
|
||||
if (comment_return)
|
||||
*comment_return = xstrdup("dsa w/o comment");
|
||||
debug("read DSA private key done");
|
||||
#ifdef DEBUG_DSS
|
||||
DSA_print_fp(stderr, dsa, 8);
|
||||
pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase);
|
||||
if (pk == NULL) {
|
||||
debug("PEM_read_PrivateKey failed");
|
||||
(void)ERR_get_error();
|
||||
} else if (pk->type == EVP_PKEY_RSA) {
|
||||
/* replace k->rsa with loaded key */
|
||||
if (k->type == KEY_RSA || k->type == KEY_UNSPEC) {
|
||||
if (k->rsa != NULL)
|
||||
RSA_free(k->rsa);
|
||||
k->rsa = EVP_PKEY_get1_RSA(pk);
|
||||
k->type = KEY_RSA;
|
||||
name = "rsa w/o comment";
|
||||
success = 1;
|
||||
#ifdef DEBUG_PK
|
||||
RSA_print_fp(stderr, k->rsa, 8);
|
||||
#endif
|
||||
return dsa != NULL ? 1 : 0;
|
||||
}
|
||||
} else if (pk->type == EVP_PKEY_DSA) {
|
||||
/* replace k->dsa with loaded key */
|
||||
if (k->type == KEY_DSA || k->type == KEY_UNSPEC) {
|
||||
if (k->dsa != NULL)
|
||||
DSA_free(k->dsa);
|
||||
k->dsa = EVP_PKEY_get1_DSA(pk);
|
||||
k->type = KEY_DSA;
|
||||
name = "dsa w/o comment";
|
||||
#ifdef DEBUG_PK
|
||||
DSA_print_fp(stderr, k->dsa, 8);
|
||||
#endif
|
||||
success = 1;
|
||||
}
|
||||
} else {
|
||||
error("PEM_read_PrivateKey: mismatch or "
|
||||
"unknown EVP_PKEY save_type %d", pk->save_type);
|
||||
}
|
||||
fclose(fp);
|
||||
if (pk != NULL)
|
||||
EVP_PKEY_free(pk);
|
||||
if (success && comment_return)
|
||||
*comment_return = xstrdup(name);
|
||||
debug("read SSH2 private key done: name %s success %d", name, success);
|
||||
return success;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -496,7 +520,7 @@ load_private_key(const char *filename, const char *passphrase, Key *key,
|
|||
return 0;
|
||||
}
|
||||
switch (key->type) {
|
||||
case KEY_RSA:
|
||||
case KEY_RSA1:
|
||||
if (key->rsa->e != NULL) {
|
||||
BN_clear_free(key->rsa->e);
|
||||
key->rsa->e = NULL;
|
||||
|
@ -505,11 +529,13 @@ load_private_key(const char *filename, const char *passphrase, Key *key,
|
|||
BN_clear_free(key->rsa->n);
|
||||
key->rsa->n = NULL;
|
||||
}
|
||||
ret = load_private_key_rsa(fd, filename, passphrase,
|
||||
ret = load_private_key_rsa1(fd, filename, passphrase,
|
||||
key->rsa, comment_return);
|
||||
break;
|
||||
case KEY_DSA:
|
||||
ret = load_private_key_dsa(fd, passphrase, key, comment_return);
|
||||
case KEY_RSA:
|
||||
case KEY_UNSPEC:
|
||||
ret = load_private_key_ssh2(fd, passphrase, key, comment_return);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -521,7 +547,6 @@ int
|
|||
do_load_public_key(const char *filename, Key *k, char **commentp)
|
||||
{
|
||||
FILE *f;
|
||||
unsigned int bits;
|
||||
char line[1024];
|
||||
char *cp;
|
||||
|
||||
|
@ -540,8 +565,7 @@ do_load_public_key(const char *filename, Key *k, char **commentp)
|
|||
for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
|
||||
;
|
||||
if (*cp) {
|
||||
bits = key_read(k, &cp);
|
||||
if (bits != 0) {
|
||||
if (key_read(k, &cp) == 1) {
|
||||
if (commentp)
|
||||
*commentp=xstrdup(filename);
|
||||
fclose(f);
|
||||
|
|
161
channels.c
161
channels.c
|
@ -40,7 +40,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: channels.c,v 1.72 2000/10/27 07:48:22 markus Exp $");
|
||||
RCSID("$OpenBSD: channels.c,v 1.73 2000/11/06 23:04:55 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "packet.h"
|
||||
|
@ -588,9 +588,12 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
|
|||
struct sockaddr addr;
|
||||
int newsock, newch;
|
||||
socklen_t addrlen;
|
||||
char buf[1024], *remote_hostname;
|
||||
char buf[1024], *remote_hostname, *rtype;
|
||||
int remote_port;
|
||||
|
||||
rtype = (c->type == SSH_CHANNEL_RPORT_LISTENER) ?
|
||||
"forwarded-tcpip" : "direct-tcpip";
|
||||
|
||||
if (FD_ISSET(c->sock, readset)) {
|
||||
debug("Connection to port %d forwarding "
|
||||
"to %.100s port %d requested.",
|
||||
|
@ -608,19 +611,26 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset)
|
|||
"connect from %.200s port %d",
|
||||
c->listening_port, c->path, c->host_port,
|
||||
remote_hostname, remote_port);
|
||||
newch = channel_new("direct-tcpip",
|
||||
|
||||
newch = channel_new(rtype,
|
||||
SSH_CHANNEL_OPENING, newsock, newsock, -1,
|
||||
c->local_window_max, c->local_maxpacket,
|
||||
0, xstrdup(buf), 1);
|
||||
if (compat20) {
|
||||
packet_start(SSH2_MSG_CHANNEL_OPEN);
|
||||
packet_put_cstring("direct-tcpip");
|
||||
packet_put_cstring(rtype);
|
||||
packet_put_int(newch);
|
||||
packet_put_int(c->local_window_max);
|
||||
packet_put_int(c->local_maxpacket);
|
||||
/* target host and port */
|
||||
packet_put_string(c->path, strlen(c->path));
|
||||
packet_put_int(c->host_port);
|
||||
if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
|
||||
/* listen address, port */
|
||||
packet_put_string(c->path, strlen(c->path));
|
||||
packet_put_int(c->listening_port);
|
||||
} else {
|
||||
/* target host, port */
|
||||
packet_put_string(c->path, strlen(c->path));
|
||||
packet_put_int(c->host_port);
|
||||
}
|
||||
/* originator host and port */
|
||||
packet_put_cstring(remote_hostname);
|
||||
packet_put_int(remote_port);
|
||||
|
@ -657,10 +667,20 @@ channel_post_auth_listener(Channel *c, fd_set * readset, fd_set * writeset)
|
|||
error("accept from auth socket: %.100s", strerror(errno));
|
||||
return;
|
||||
}
|
||||
newch = channel_allocate(SSH_CHANNEL_OPENING, newsock,
|
||||
xstrdup("accepted auth socket"));
|
||||
packet_start(SSH_SMSG_AGENT_OPEN);
|
||||
packet_put_int(newch);
|
||||
newch = channel_new("accepted auth socket",
|
||||
SSH_CHANNEL_OPENING, newsock, newsock, -1,
|
||||
c->local_window_max, c->local_maxpacket,
|
||||
0, xstrdup("accepted auth socket"), 1);
|
||||
if (compat20) {
|
||||
packet_start(SSH2_MSG_CHANNEL_OPEN);
|
||||
packet_put_cstring("auth-agent@openssh.com");
|
||||
packet_put_int(newch);
|
||||
packet_put_int(c->local_window_max);
|
||||
packet_put_int(c->local_maxpacket);
|
||||
} else {
|
||||
packet_start(SSH_SMSG_AGENT_OPEN);
|
||||
packet_put_int(newch);
|
||||
}
|
||||
packet_send();
|
||||
}
|
||||
}
|
||||
|
@ -820,11 +840,15 @@ channel_handler_init_20(void)
|
|||
channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_20;
|
||||
channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
|
||||
channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
|
||||
channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener;
|
||||
channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
|
||||
channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
|
||||
|
||||
channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_2;
|
||||
channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
|
||||
channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener;
|
||||
channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
|
||||
channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1326,6 +1350,7 @@ channel_stop_listening()
|
|||
channel_free(i);
|
||||
break;
|
||||
case SSH_CHANNEL_PORT_LISTENER:
|
||||
case SSH_CHANNEL_RPORT_LISTENER:
|
||||
case SSH_CHANNEL_X11_LISTENER:
|
||||
close(channels[i].sock);
|
||||
channel_free(i);
|
||||
|
@ -1369,6 +1394,7 @@ channel_still_open()
|
|||
case SSH_CHANNEL_FREE:
|
||||
case SSH_CHANNEL_X11_LISTENER:
|
||||
case SSH_CHANNEL_PORT_LISTENER:
|
||||
case SSH_CHANNEL_RPORT_LISTENER:
|
||||
case SSH_CHANNEL_CLOSED:
|
||||
case SSH_CHANNEL_AUTH_SOCKET:
|
||||
continue;
|
||||
|
@ -1414,6 +1440,7 @@ channel_open_message()
|
|||
case SSH_CHANNEL_FREE:
|
||||
case SSH_CHANNEL_X11_LISTENER:
|
||||
case SSH_CHANNEL_PORT_LISTENER:
|
||||
case SSH_CHANNEL_RPORT_LISTENER:
|
||||
case SSH_CHANNEL_CLOSED:
|
||||
case SSH_CHANNEL_AUTH_SOCKET:
|
||||
continue;
|
||||
|
@ -1446,19 +1473,44 @@ channel_open_message()
|
|||
* Initiate forwarding of connections to local port "port" through the secure
|
||||
* channel to host:port from remote side.
|
||||
*/
|
||||
|
||||
void
|
||||
channel_request_local_forwarding(u_short port, const char *host,
|
||||
u_short host_port, int gateway_ports)
|
||||
channel_request_local_forwarding(u_short listen_port, const char *host_to_connect,
|
||||
u_short port_to_connect, int gateway_ports)
|
||||
{
|
||||
int success, ch, sock, on = 1;
|
||||
channel_request_forwarding(
|
||||
NULL, listen_port,
|
||||
host_to_connect, port_to_connect,
|
||||
gateway_ports, /*remote_fwd*/ 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If 'remote_fwd' is true we have a '-R style' listener for protocol 2
|
||||
* (SSH_CHANNEL_RPORT_LISTENER).
|
||||
*/
|
||||
void
|
||||
channel_request_forwarding(
|
||||
const char *listen_address, u_short listen_port,
|
||||
const char *host_to_connect, u_short port_to_connect,
|
||||
int gateway_ports, int remote_fwd)
|
||||
{
|
||||
int success, ch, sock, on = 1, ctype;
|
||||
struct addrinfo hints, *ai, *aitop;
|
||||
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
|
||||
const char *host;
|
||||
struct linger linger;
|
||||
|
||||
if (remote_fwd) {
|
||||
host = listen_address;
|
||||
ctype = SSH_CHANNEL_RPORT_LISTENER;
|
||||
} else {
|
||||
host = host_to_connect;
|
||||
ctype =SSH_CHANNEL_PORT_LISTENER;
|
||||
}
|
||||
|
||||
if (strlen(host) > sizeof(channels[0].path) - 1)
|
||||
packet_disconnect("Forward host name too long.");
|
||||
|
||||
/* XXX listen_address is currently ignored */
|
||||
/*
|
||||
* getaddrinfo returns a loopback address if the hostname is
|
||||
* set to NULL and hints.ai_flags is not AI_PASSIVE
|
||||
|
@ -1467,7 +1519,7 @@ channel_request_local_forwarding(u_short port, const char *host,
|
|||
hints.ai_family = IPv4or6;
|
||||
hints.ai_flags = gateway_ports ? AI_PASSIVE : 0;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
snprintf(strport, sizeof strport, "%d", port);
|
||||
snprintf(strport, sizeof strport, "%d", listen_port);
|
||||
if (getaddrinfo(NULL, strport, &hints, &aitop) != 0)
|
||||
packet_disconnect("getaddrinfo: fatal error");
|
||||
|
||||
|
@ -1477,7 +1529,7 @@ channel_request_local_forwarding(u_short port, const char *host,
|
|||
continue;
|
||||
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
|
||||
strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
|
||||
error("channel_request_local_forwarding: getnameinfo failed");
|
||||
error("channel_request_forwarding: getnameinfo failed");
|
||||
continue;
|
||||
}
|
||||
/* Create a port to listen for the host. */
|
||||
|
@ -1515,18 +1567,16 @@ channel_request_local_forwarding(u_short port, const char *host,
|
|||
continue;
|
||||
}
|
||||
/* Allocate a channel number for the socket. */
|
||||
ch = channel_new(
|
||||
"port listener", SSH_CHANNEL_PORT_LISTENER,
|
||||
sock, sock, -1,
|
||||
ch = channel_new("port listener", ctype, sock, sock, -1,
|
||||
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
|
||||
0, xstrdup("port listener"), 1);
|
||||
strlcpy(channels[ch].path, host, sizeof(channels[ch].path));
|
||||
channels[ch].host_port = host_port;
|
||||
channels[ch].listening_port = port;
|
||||
channels[ch].host_port = port_to_connect;
|
||||
channels[ch].listening_port = listen_port;
|
||||
success = 1;
|
||||
}
|
||||
if (success == 0)
|
||||
packet_disconnect("cannot listen port: %d", port);
|
||||
packet_disconnect("cannot listen port: %d", listen_port); /*XXX ?disconnect? */
|
||||
freeaddrinfo(aitop);
|
||||
}
|
||||
|
||||
|
@ -1536,19 +1586,15 @@ channel_request_local_forwarding(u_short port, const char *host,
|
|||
*/
|
||||
|
||||
void
|
||||
channel_request_remote_forwarding(u_short listen_port, const char *host_to_connect,
|
||||
u_short port_to_connect)
|
||||
channel_request_remote_forwarding(u_short listen_port,
|
||||
const char *host_to_connect, u_short port_to_connect)
|
||||
{
|
||||
int payload_len;
|
||||
int payload_len, type, success = 0;
|
||||
|
||||
/* Record locally that connection to this host/port is permitted. */
|
||||
if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
|
||||
fatal("channel_request_remote_forwarding: too many forwards");
|
||||
|
||||
permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect);
|
||||
permitted_opens[num_permitted_opens].port_to_connect = port_to_connect;
|
||||
permitted_opens[num_permitted_opens].listen_port = listen_port;
|
||||
num_permitted_opens++;
|
||||
|
||||
/* Send the forward request to the remote side. */
|
||||
if (compat20) {
|
||||
const char *address_to_bind = "0.0.0.0";
|
||||
|
@ -1557,6 +1603,10 @@ channel_request_remote_forwarding(u_short listen_port, const char *host_to_conne
|
|||
packet_put_char(0); /* boolean: want reply */
|
||||
packet_put_cstring(address_to_bind);
|
||||
packet_put_int(listen_port);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
/* Assume that server accepts the request */
|
||||
success = 1;
|
||||
} else {
|
||||
packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
|
||||
packet_put_int(listen_port);
|
||||
|
@ -1564,11 +1614,27 @@ channel_request_remote_forwarding(u_short listen_port, const char *host_to_conne
|
|||
packet_put_int(port_to_connect);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
/*
|
||||
* Wait for response from the remote side. It will send a disconnect
|
||||
* message on failure, and we will never see it here.
|
||||
*/
|
||||
packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);
|
||||
|
||||
/* Wait for response from the remote side. */
|
||||
type = packet_read(&payload_len);
|
||||
switch (type) {
|
||||
case SSH_SMSG_SUCCESS:
|
||||
success = 1;
|
||||
break;
|
||||
case SSH_SMSG_FAILURE:
|
||||
log("Warning: Server denied remote port forwarding.");
|
||||
break;
|
||||
default:
|
||||
/* Unknown packet */
|
||||
packet_disconnect("Protocol error for port forward request:"
|
||||
"received packet type %d.", type);
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect);
|
||||
permitted_opens[num_permitted_opens].port_to_connect = port_to_connect;
|
||||
permitted_opens[num_permitted_opens].listen_port = listen_port;
|
||||
num_permitted_opens++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1598,9 +1664,7 @@ channel_input_port_forward_request(int is_root, int gateway_ports)
|
|||
packet_disconnect("Requested forwarding of port %d but user is not root.",
|
||||
port);
|
||||
#endif
|
||||
/*
|
||||
* Initiate forwarding,
|
||||
*/
|
||||
/* Initiate forwarding */
|
||||
channel_request_local_forwarding(port, hostname, host_port, gateway_ports);
|
||||
|
||||
/* Free the argument string. */
|
||||
|
@ -1656,6 +1720,18 @@ channel_connect_to(const char *host, u_short host_port)
|
|||
/* success */
|
||||
return sock;
|
||||
}
|
||||
int
|
||||
channel_connect_by_listen_adress(u_short listen_port)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < num_permitted_opens; i++)
|
||||
if (permitted_opens[i].listen_port == listen_port)
|
||||
return channel_connect_to(
|
||||
permitted_opens[i].host_to_connect,
|
||||
permitted_opens[i].port_to_connect);
|
||||
debug("channel_connect_by_listen_adress: unknown listen_port %d", listen_port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called after receiving PORT_OPEN message. This attempts to
|
||||
|
@ -2233,8 +2309,11 @@ auth_input_request_forwarding(struct passwd * pw)
|
|||
packet_disconnect("listen: %.100s", strerror(errno));
|
||||
|
||||
/* Allocate a channel for the authentication agent socket. */
|
||||
newch = channel_allocate(SSH_CHANNEL_AUTH_SOCKET, sock,
|
||||
xstrdup("auth socket"));
|
||||
newch = channel_new("auth socket",
|
||||
SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
|
||||
CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
|
||||
0, xstrdup("auth socket"), 1);
|
||||
|
||||
strlcpy(channels[newch].path, channel_forwarded_auth_socket_name,
|
||||
sizeof(channels[newch].path));
|
||||
return 1;
|
||||
|
|
18
channels.h
18
channels.h
|
@ -32,7 +32,7 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/* RCSID("$OpenBSD: channels.h,v 1.22 2000/10/27 07:48:22 markus Exp $"); */
|
||||
/* RCSID("$OpenBSD: channels.h,v 1.23 2000/11/06 23:04:56 markus Exp $"); */
|
||||
|
||||
#ifndef CHANNELS_H
|
||||
#define CHANNELS_H
|
||||
|
@ -49,7 +49,8 @@
|
|||
#define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */
|
||||
#define SSH_CHANNEL_OUTPUT_DRAINING 9 /* sending remaining data to app */
|
||||
#define SSH_CHANNEL_LARVAL 10 /* larval session */
|
||||
#define SSH_CHANNEL_MAX_TYPE 11
|
||||
#define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */
|
||||
#define SSH_CHANNEL_MAX_TYPE 12
|
||||
|
||||
/*
|
||||
* Data structure for channel data. This is iniailized in channel_allocate
|
||||
|
@ -147,7 +148,6 @@ void channel_input_open_confirmation(int type, int plen, void *ctxt);
|
|||
void channel_input_open_failure(int type, int plen, void *ctxt);
|
||||
void channel_input_port_open(int type, int plen, void *ctxt);
|
||||
void channel_input_window_adjust(int type, int plen, void *ctxt);
|
||||
void channel_input_open(int type, int plen, void *ctxt);
|
||||
|
||||
/* Sets specific protocol options. */
|
||||
void channel_set_options(int hostname_in_open);
|
||||
|
@ -202,12 +202,15 @@ char *channel_open_message(void);
|
|||
|
||||
/*
|
||||
* Initiate forwarding of connections to local port "port" through the secure
|
||||
* channel to host:port from remote side. This never returns if there was an
|
||||
* error.
|
||||
* channel to host:port from remote side.
|
||||
*/
|
||||
void
|
||||
channel_request_local_forwarding(u_short port, const char *host,
|
||||
u_short remote_port, int gateway_ports);
|
||||
channel_request_local_forwarding(u_short listen_port,
|
||||
const char *host_to_connect, u_short port_to_connect, int gateway_ports);
|
||||
void
|
||||
channel_request_forwarding(const char *listen_address, u_short listen_port,
|
||||
const char *host_to_connect, u_short port_to_connect, int gateway_ports,
|
||||
int remote_fwd);
|
||||
|
||||
/*
|
||||
* Initiate forwarding of connections to port "port" on remote host through
|
||||
|
@ -288,6 +291,7 @@ void auth_input_open_request(int type, int plen, void *ctxt);
|
|||
|
||||
/* XXX */
|
||||
int channel_connect_to(const char *host, u_short host_port);
|
||||
int channel_connect_by_listen_adress(u_short listen_port);
|
||||
int x11_connect_display(void);
|
||||
|
||||
#endif
|
||||
|
|
122
clientloop.c
122
clientloop.c
|
@ -59,7 +59,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: clientloop.c,v 1.39 2000/10/27 07:48:22 markus Exp $");
|
||||
RCSID("$OpenBSD: clientloop.c,v 1.40 2000/11/06 23:04:56 markus Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
|
@ -75,6 +75,10 @@ RCSID("$OpenBSD: clientloop.c,v 1.39 2000/10/27 07:48:22 markus Exp $");
|
|||
#include "buffer.h"
|
||||
#include "bufaux.h"
|
||||
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include "key.h"
|
||||
#include "authfd.h"
|
||||
|
||||
/* import options */
|
||||
extern Options options;
|
||||
|
@ -1016,13 +1020,99 @@ client_input_exit_status(int type, int plen, void *ctxt)
|
|||
quit_pending = 1;
|
||||
}
|
||||
|
||||
Channel *
|
||||
client_request_forwarded_tcpip(const char *request_type, int rchan)
|
||||
{
|
||||
Channel* c = NULL;
|
||||
char *listen_address, *originator_address;
|
||||
int listen_port, originator_port;
|
||||
int sock, newch;
|
||||
|
||||
/* Get rest of the packet */
|
||||
listen_address = packet_get_string(NULL);
|
||||
listen_port = packet_get_int();
|
||||
originator_address = packet_get_string(NULL);
|
||||
originator_port = packet_get_int();
|
||||
packet_done();
|
||||
|
||||
debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d",
|
||||
listen_address, listen_port, originator_address, originator_port);
|
||||
|
||||
sock = channel_connect_by_listen_adress(listen_port);
|
||||
if (sock >= 0) {
|
||||
newch = channel_new("forwarded-tcpip",
|
||||
SSH_CHANNEL_OPEN, sock, sock, -1,
|
||||
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
|
||||
xstrdup(originator_address), 1);
|
||||
c = channel_lookup(newch);
|
||||
}
|
||||
xfree(originator_address);
|
||||
xfree(listen_address);
|
||||
return c;
|
||||
}
|
||||
|
||||
Channel*
|
||||
client_request_x11(const char *request_type, int rchan)
|
||||
{
|
||||
Channel *c = NULL;
|
||||
char *originator;
|
||||
int originator_port;
|
||||
int sock, newch;
|
||||
|
||||
if (!options.forward_x11) {
|
||||
error("Warning: ssh server tried X11 forwarding.");
|
||||
error("Warning: this is probably a break in attempt by a malicious server.");
|
||||
return NULL;
|
||||
}
|
||||
originator = packet_get_string(NULL);
|
||||
if (datafellows & SSH_BUG_X11FWD) {
|
||||
debug2("buggy server: x11 request w/o originator_port");
|
||||
originator_port = 0;
|
||||
} else {
|
||||
originator_port = packet_get_int();
|
||||
}
|
||||
packet_done();
|
||||
/* XXX check permission */
|
||||
sock = x11_connect_display();
|
||||
if (sock >= 0) {
|
||||
newch = channel_new("x11",
|
||||
SSH_CHANNEL_X11_OPEN, sock, sock, -1,
|
||||
CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0,
|
||||
xstrdup("x11"), 1);
|
||||
c = channel_lookup(newch);
|
||||
}
|
||||
xfree(originator);
|
||||
return c;
|
||||
}
|
||||
|
||||
Channel*
|
||||
client_request_agent(const char *request_type, int rchan)
|
||||
{
|
||||
Channel *c = NULL;
|
||||
int sock, newch;
|
||||
|
||||
if (!options.forward_agent) {
|
||||
error("Warning: ssh server tried agent forwarding.");
|
||||
error("Warning: this is probably a break in attempt by a malicious server.");
|
||||
return NULL;
|
||||
}
|
||||
sock = ssh_get_authentication_socket();
|
||||
if (sock >= 0) {
|
||||
newch = channel_new("authentication agent connection",
|
||||
SSH_CHANNEL_OPEN, sock, sock, -1,
|
||||
CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0,
|
||||
xstrdup("authentication agent connection"), 1);
|
||||
c = channel_lookup(newch);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/* XXXX move to generic input handler */
|
||||
void
|
||||
client_input_channel_open(int type, int plen, void *ctxt)
|
||||
{
|
||||
Channel *c = NULL;
|
||||
char *ctype;
|
||||
int id;
|
||||
unsigned int len;
|
||||
int rchan;
|
||||
int rmaxpack;
|
||||
|
@ -1036,28 +1126,12 @@ client_input_channel_open(int type, int plen, void *ctxt)
|
|||
debug("client_input_channel_open: ctype %s rchan %d win %d max %d",
|
||||
ctype, rchan, rwindow, rmaxpack);
|
||||
|
||||
if (strcmp(ctype, "x11") == 0 && options.forward_x11) {
|
||||
int sock;
|
||||
char *originator;
|
||||
int originator_port;
|
||||
originator = packet_get_string(NULL);
|
||||
if (datafellows & SSH_BUG_X11FWD) {
|
||||
debug2("buggy server: x11 request w/o originator_port");
|
||||
originator_port = 0;
|
||||
} else {
|
||||
originator_port = packet_get_int();
|
||||
}
|
||||
packet_done();
|
||||
/* XXX check permission */
|
||||
xfree(originator);
|
||||
/* XXX move to channels.c */
|
||||
sock = x11_connect_display();
|
||||
if (sock >= 0) {
|
||||
id = channel_new("x11", SSH_CHANNEL_X11_OPEN,
|
||||
sock, sock, -1, CHAN_X11_WINDOW_DEFAULT,
|
||||
CHAN_X11_PACKET_DEFAULT, 0, xstrdup("x11"), 1);
|
||||
c = channel_lookup(id);
|
||||
}
|
||||
if (strcmp(ctype, "forwarded-tcpip") == 0) {
|
||||
c = client_request_forwarded_tcpip(ctype, rchan);
|
||||
} else if (strcmp(ctype, "x11") == 0) {
|
||||
c = client_request_x11(ctype, rchan);
|
||||
} else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
|
||||
c = client_request_agent(ctype, rchan);
|
||||
}
|
||||
/* XXX duplicate : */
|
||||
if (c != NULL) {
|
||||
|
|
|
@ -19,13 +19,27 @@ RETVAL=0
|
|||
|
||||
# Some functions to make the below more readable
|
||||
KEYGEN=/usr/bin/ssh-keygen
|
||||
RSA_KEY=/etc/ssh/ssh_host_key
|
||||
RSA1_KEY=/etc/ssh/ssh_host_key
|
||||
RSA_KEY=/etc/ssh/ssh_host_rsa_key
|
||||
DSA_KEY=/etc/ssh/ssh_host_dsa_key
|
||||
PID_FILE=/var/run/sshd.pid
|
||||
do_rsa1_keygen() {
|
||||
if ! test -f $RSA1_KEY ; then
|
||||
echo -n "Generating SSH1 RSA host key: "
|
||||
if $KEYGEN -q -t rsa1 -f $RSA1_KEY -C '' -N '' >&/dev/null; then
|
||||
success "RSA1 key generation"
|
||||
echo
|
||||
else
|
||||
failure "RSA1 key generation"
|
||||
echo
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
do_rsa_keygen() {
|
||||
if $KEYGEN -R && ! test -f $RSA_KEY ; then
|
||||
echo -n "Generating SSH RSA host key: "
|
||||
if $KEYGEN -q -b 1024 -f $RSA_KEY -C '' -N '' >&/dev/null; then
|
||||
if ! test -f $RSA_KEY ; then
|
||||
echo -n "Generating SSH2 RSA host key: "
|
||||
if $KEYGEN -q -t rsa -f $RSA_KEY -C '' -N '' >&/dev/null; then
|
||||
success "RSA key generation"
|
||||
echo
|
||||
else
|
||||
|
@ -37,8 +51,8 @@ do_rsa_keygen() {
|
|||
}
|
||||
do_dsa_keygen() {
|
||||
if ! test -f $DSA_KEY ; then
|
||||
echo -n "Generating SSH DSA host key: "
|
||||
if $KEYGEN -q -d -b 1024 -f $DSA_KEY -C '' -N '' >&/dev/null; then
|
||||
echo -n "Generating SSH2 DSA host key: "
|
||||
if $KEYGEN -q -t dsa -f $DSA_KEY -C '' -N '' >&/dev/null; then
|
||||
success "DSA key generation"
|
||||
echo
|
||||
else
|
||||
|
@ -52,6 +66,7 @@ do_dsa_keygen() {
|
|||
case "$1" in
|
||||
start)
|
||||
# Create keys if necessary
|
||||
do_rsa1_keygen;
|
||||
do_rsa_keygen;
|
||||
do_dsa_keygen;
|
||||
|
||||
|
|
12
hostfile.c
12
hostfile.c
|
@ -36,7 +36,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: hostfile.c,v 1.20 2000/09/07 20:27:51 deraadt Exp $");
|
||||
RCSID("$OpenBSD: hostfile.c,v 1.21 2000/11/12 19:50:37 markus Exp $");
|
||||
|
||||
#include "packet.h"
|
||||
#include "match.h"
|
||||
|
@ -54,15 +54,13 @@ RCSID("$OpenBSD: hostfile.c,v 1.20 2000/09/07 20:27:51 deraadt Exp $");
|
|||
int
|
||||
hostfile_read_key(char **cpp, unsigned int *bitsp, Key *ret)
|
||||
{
|
||||
unsigned int bits;
|
||||
char *cp;
|
||||
|
||||
/* Skip leading whitespace. */
|
||||
for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
|
||||
;
|
||||
|
||||
bits = key_read(ret, &cp);
|
||||
if (bits == 0)
|
||||
if (key_read(ret, &cp) != 1)
|
||||
return 0;
|
||||
|
||||
/* Skip trailing whitespace. */
|
||||
|
@ -71,14 +69,14 @@ hostfile_read_key(char **cpp, unsigned int *bitsp, Key *ret)
|
|||
|
||||
/* Return results. */
|
||||
*cpp = cp;
|
||||
*bitsp = bits;
|
||||
*bitsp = key_size(ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
|
||||
{
|
||||
Key *k = key_new(KEY_RSA);
|
||||
Key *k = key_new(KEY_RSA1);
|
||||
int ret = hostfile_read_key(cpp, bitsp, k);
|
||||
BN_copy(e, k->rsa->e);
|
||||
BN_copy(n, k->rsa->n);
|
||||
|
@ -89,7 +87,7 @@ auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
|
|||
int
|
||||
hostfile_check_key(int bits, Key *key, const char *host, const char *filename, int linenum)
|
||||
{
|
||||
if (key == NULL || key->type != KEY_RSA || key->rsa == NULL)
|
||||
if (key == NULL || key->type != KEY_RSA1 || key->rsa == NULL)
|
||||
return 1;
|
||||
if (bits != BN_num_bits(key->rsa->n)) {
|
||||
log("Warning: %s, line %d: keysize mismatch for host %s: "
|
||||
|
|
12
kex.c
12
kex.c
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: kex.c,v 1.12 2000/10/11 20:27:23 markus Exp $");
|
||||
RCSID("$OpenBSD: kex.c,v 1.13 2000/11/12 19:50:37 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "ssh2.h"
|
||||
|
@ -43,6 +43,7 @@ RCSID("$OpenBSD: kex.c,v 1.12 2000/10/11 20:27:23 markus Exp $");
|
|||
#include <openssl/pem.h>
|
||||
|
||||
#include "kex.h"
|
||||
#include "key.h"
|
||||
|
||||
#define KEX_COOKIE_LEN 16
|
||||
|
||||
|
@ -454,11 +455,12 @@ choose_kex(Kex *k, char *client, char *server)
|
|||
void
|
||||
choose_hostkeyalg(Kex *k, char *client, char *server)
|
||||
{
|
||||
k->hostkeyalg = get_match(client, server);
|
||||
if (k->hostkeyalg == NULL)
|
||||
char *hostkeyalg = get_match(client, server);
|
||||
if (hostkeyalg == NULL)
|
||||
fatal("no hostkey alg");
|
||||
if (strcmp(k->hostkeyalg, KEX_DSS) != 0)
|
||||
fatal("bad hostkey alg %s", k->hostkeyalg);
|
||||
k->hostkey_type = key_type_from_name(hostkeyalg);
|
||||
if (k->hostkey_type == KEY_UNSPEC)
|
||||
fatal("bad hostkey alg '%s'", hostkeyalg);
|
||||
}
|
||||
|
||||
Kex *
|
||||
|
|
2
kex.h
2
kex.h
|
@ -85,7 +85,7 @@ struct Kex {
|
|||
int we_need;
|
||||
int server;
|
||||
char *name;
|
||||
char *hostkeyalg;
|
||||
int hostkey_type;
|
||||
int kex_type;
|
||||
};
|
||||
|
||||
|
|
388
key.c
388
key.c
|
@ -39,12 +39,14 @@
|
|||
#include <openssl/evp.h>
|
||||
#include "xmalloc.h"
|
||||
#include "key.h"
|
||||
#include "dsa.h"
|
||||
#include "rsa.h"
|
||||
#include "ssh-dss.h"
|
||||
#include "ssh-rsa.h"
|
||||
#include "uuencode.h"
|
||||
#include "buffer.h"
|
||||
#include "bufaux.h"
|
||||
|
||||
RCSID("$OpenBSD: key.c,v 1.11 2000/09/07 20:27:51 deraadt Exp $");
|
||||
|
||||
#define SSH_DSS "ssh-dss"
|
||||
RCSID("$OpenBSD: key.c,v 1.12 2000/11/12 19:50:37 markus Exp $");
|
||||
|
||||
Key *
|
||||
key_new(int type)
|
||||
|
@ -57,6 +59,7 @@ key_new(int type)
|
|||
k->dsa = NULL;
|
||||
k->rsa = NULL;
|
||||
switch (k->type) {
|
||||
case KEY_RSA1:
|
||||
case KEY_RSA:
|
||||
rsa = RSA_new();
|
||||
rsa->n = BN_new();
|
||||
|
@ -71,7 +74,7 @@ key_new(int type)
|
|||
dsa->pub_key = BN_new();
|
||||
k->dsa = dsa;
|
||||
break;
|
||||
case KEY_EMPTY:
|
||||
case KEY_UNSPEC:
|
||||
break;
|
||||
default:
|
||||
fatal("key_new: bad key type %d", k->type);
|
||||
|
@ -79,10 +82,35 @@ key_new(int type)
|
|||
}
|
||||
return k;
|
||||
}
|
||||
Key *
|
||||
key_new_private(int type)
|
||||
{
|
||||
Key *k = key_new(type);
|
||||
switch (k->type) {
|
||||
case KEY_RSA1:
|
||||
case KEY_RSA:
|
||||
k->rsa->d = BN_new();
|
||||
k->rsa->iqmp = BN_new();
|
||||
k->rsa->q = BN_new();
|
||||
k->rsa->p = BN_new();
|
||||
k->rsa->dmq1 = BN_new();
|
||||
k->rsa->dmp1 = BN_new();
|
||||
break;
|
||||
case KEY_DSA:
|
||||
k->dsa->priv_key = BN_new();
|
||||
break;
|
||||
case KEY_UNSPEC:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
void
|
||||
key_free(Key *k)
|
||||
{
|
||||
switch (k->type) {
|
||||
case KEY_RSA1:
|
||||
case KEY_RSA:
|
||||
if (k->rsa != NULL)
|
||||
RSA_free(k->rsa);
|
||||
|
@ -93,6 +121,8 @@ key_free(Key *k)
|
|||
DSA_free(k->dsa);
|
||||
k->dsa = NULL;
|
||||
break;
|
||||
case KEY_UNSPEC:
|
||||
break;
|
||||
default:
|
||||
fatal("key_free: bad key type %d", k->type);
|
||||
break;
|
||||
|
@ -105,6 +135,7 @@ key_equal(Key *a, Key *b)
|
|||
if (a == NULL || b == NULL || a->type != b->type)
|
||||
return 0;
|
||||
switch (a->type) {
|
||||
case KEY_RSA1:
|
||||
case KEY_RSA:
|
||||
return a->rsa != NULL && b->rsa != NULL &&
|
||||
BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
|
||||
|
@ -136,8 +167,9 @@ key_fingerprint(Key *k)
|
|||
int len = 0;
|
||||
int nlen, elen;
|
||||
|
||||
retval[0] = '\0';
|
||||
switch (k->type) {
|
||||
case KEY_RSA:
|
||||
case KEY_RSA1:
|
||||
nlen = BN_num_bytes(k->rsa->n);
|
||||
elen = BN_num_bytes(k->rsa->e);
|
||||
len = nlen + elen;
|
||||
|
@ -146,14 +178,16 @@ key_fingerprint(Key *k)
|
|||
BN_bn2bin(k->rsa->e, blob + nlen);
|
||||
break;
|
||||
case KEY_DSA:
|
||||
dsa_make_key_blob(k, &blob, &len);
|
||||
case KEY_RSA:
|
||||
key_to_blob(k, &blob, &len);
|
||||
break;
|
||||
case KEY_UNSPEC:
|
||||
return retval;
|
||||
break;
|
||||
default:
|
||||
fatal("key_fingerprint: bad key type %d", k->type);
|
||||
break;
|
||||
}
|
||||
retval[0] = '\0';
|
||||
|
||||
if (blob != NULL) {
|
||||
int i;
|
||||
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||
|
@ -229,56 +263,106 @@ write_bignum(FILE *f, BIGNUM *num)
|
|||
free(buf);
|
||||
return 1;
|
||||
}
|
||||
unsigned int
|
||||
|
||||
/* returns 1 ok, -1 error, 0 type mismatch */
|
||||
int
|
||||
key_read(Key *ret, char **cpp)
|
||||
{
|
||||
Key *k;
|
||||
unsigned int bits = 0;
|
||||
char *cp;
|
||||
int len, n;
|
||||
int success = -1;
|
||||
char *cp, *space;
|
||||
int len, n, type;
|
||||
u_int bits;
|
||||
unsigned char *blob;
|
||||
|
||||
cp = *cpp;
|
||||
|
||||
switch(ret->type) {
|
||||
case KEY_RSA:
|
||||
case KEY_RSA1:
|
||||
/* Get number of bits. */
|
||||
if (*cp < '0' || *cp > '9')
|
||||
return 0; /* Bad bit count... */
|
||||
return -1; /* Bad bit count... */
|
||||
for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
|
||||
bits = 10 * bits + *cp - '0';
|
||||
if (bits == 0)
|
||||
return 0;
|
||||
return -1;
|
||||
*cpp = cp;
|
||||
/* Get public exponent, public modulus. */
|
||||
if (!read_bignum(cpp, ret->rsa->e))
|
||||
return 0;
|
||||
return -1;
|
||||
if (!read_bignum(cpp, ret->rsa->n))
|
||||
return 0;
|
||||
return -1;
|
||||
success = 1;
|
||||
break;
|
||||
case KEY_UNSPEC:
|
||||
case KEY_RSA:
|
||||
case KEY_DSA:
|
||||
if (strncmp(cp, SSH_DSS " ", 7) != 0)
|
||||
space = strchr(cp, ' ');
|
||||
if (space == NULL) {
|
||||
debug3("key_read: no space");
|
||||
return -1;
|
||||
}
|
||||
*space = '\0';
|
||||
type = key_type_from_name(cp);
|
||||
*space = ' ';
|
||||
if (type == KEY_UNSPEC) {
|
||||
debug3("key_read: no key found");
|
||||
return -1;
|
||||
}
|
||||
cp = space+1;
|
||||
if (*cp == '\0') {
|
||||
debug3("key_read: short string");
|
||||
return -1;
|
||||
}
|
||||
if (ret->type == KEY_UNSPEC) {
|
||||
ret->type = type;
|
||||
} else if (ret->type != type) {
|
||||
/* is a key, but different type */
|
||||
debug3("key_read: type mismatch");
|
||||
return 0;
|
||||
cp += 7;
|
||||
}
|
||||
len = 2*strlen(cp);
|
||||
blob = xmalloc(len);
|
||||
n = uudecode(cp, blob, len);
|
||||
if (n < 0) {
|
||||
error("key_read: uudecode %s failed", cp);
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
k = dsa_key_from_blob(blob, n);
|
||||
k = key_from_blob(blob, n);
|
||||
if (k == NULL) {
|
||||
error("key_read: dsa_key_from_blob %s failed", cp);
|
||||
return 0;
|
||||
error("key_read: key_from_blob %s failed", cp);
|
||||
return -1;
|
||||
}
|
||||
xfree(blob);
|
||||
if (ret->dsa != NULL)
|
||||
DSA_free(ret->dsa);
|
||||
ret->dsa = k->dsa;
|
||||
k->dsa = NULL;
|
||||
if (k->type != type) {
|
||||
error("key_read: type mismatch: encoding error");
|
||||
key_free(k);
|
||||
return -1;
|
||||
}
|
||||
/*XXXX*/
|
||||
if (ret->type == KEY_RSA) {
|
||||
if (ret->rsa != NULL)
|
||||
RSA_free(ret->rsa);
|
||||
ret->rsa = k->rsa;
|
||||
k->rsa = NULL;
|
||||
success = 1;
|
||||
#ifdef DEBUG_PK
|
||||
RSA_print_fp(stderr, ret->rsa, 8);
|
||||
#endif
|
||||
} else {
|
||||
if (ret->dsa != NULL)
|
||||
DSA_free(ret->dsa);
|
||||
ret->dsa = k->dsa;
|
||||
k->dsa = NULL;
|
||||
success = 1;
|
||||
#ifdef DEBUG_PK
|
||||
DSA_print_fp(stderr, ret->dsa, 8);
|
||||
#endif
|
||||
}
|
||||
/*XXXX*/
|
||||
if (success != 1)
|
||||
break;
|
||||
key_free(k);
|
||||
bits = BN_num_bits(ret->dsa->p);
|
||||
/* advance cp: skip whitespace and data */
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
|
@ -290,7 +374,7 @@ key_read(Key *ret, char **cpp)
|
|||
fatal("key_read: bad key type: %d", ret->type);
|
||||
break;
|
||||
}
|
||||
return bits;
|
||||
return success;
|
||||
}
|
||||
int
|
||||
key_write(Key *key, FILE *f)
|
||||
|
@ -298,7 +382,7 @@ key_write(Key *key, FILE *f)
|
|||
int success = 0;
|
||||
unsigned int bits = 0;
|
||||
|
||||
if (key->type == KEY_RSA && key->rsa != NULL) {
|
||||
if (key->type == KEY_RSA1 && key->rsa != NULL) {
|
||||
/* size of modulus 'n' */
|
||||
bits = BN_num_bits(key->rsa->n);
|
||||
fprintf(f, "%u", bits);
|
||||
|
@ -308,14 +392,15 @@ key_write(Key *key, FILE *f)
|
|||
} else {
|
||||
error("key_write: failed for RSA key");
|
||||
}
|
||||
} else if (key->type == KEY_DSA && key->dsa != NULL) {
|
||||
} else if ((key->type == KEY_DSA && key->dsa != NULL) ||
|
||||
(key->type == KEY_RSA && key->rsa != NULL)) {
|
||||
int len, n;
|
||||
unsigned char *blob, *uu;
|
||||
dsa_make_key_blob(key, &blob, &len);
|
||||
key_to_blob(key, &blob, &len);
|
||||
uu = xmalloc(2*len);
|
||||
n = uuencode(blob, len, uu, 2*len);
|
||||
if (n > 0) {
|
||||
fprintf(f, "%s %s", SSH_DSS, uu);
|
||||
fprintf(f, "%s %s", key_ssh_name(key), uu);
|
||||
success = 1;
|
||||
}
|
||||
xfree(blob);
|
||||
|
@ -327,6 +412,9 @@ char *
|
|||
key_type(Key *k)
|
||||
{
|
||||
switch (k->type) {
|
||||
case KEY_RSA1:
|
||||
return "RSA1";
|
||||
break;
|
||||
case KEY_RSA:
|
||||
return "RSA";
|
||||
break;
|
||||
|
@ -336,9 +424,23 @@ key_type(Key *k)
|
|||
}
|
||||
return "unknown";
|
||||
}
|
||||
unsigned int
|
||||
char *
|
||||
key_ssh_name(Key *k)
|
||||
{
|
||||
switch (k->type) {
|
||||
case KEY_RSA:
|
||||
return "ssh-rsa";
|
||||
break;
|
||||
case KEY_DSA:
|
||||
return "ssh-dss";
|
||||
break;
|
||||
}
|
||||
return "ssh-unknown";
|
||||
}
|
||||
u_int
|
||||
key_size(Key *k){
|
||||
switch (k->type) {
|
||||
case KEY_RSA1:
|
||||
case KEY_RSA:
|
||||
return BN_num_bits(k->rsa->n);
|
||||
break;
|
||||
|
@ -348,3 +450,219 @@ key_size(Key *k){
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
RSA *
|
||||
rsa_generate_private_key(unsigned int bits)
|
||||
{
|
||||
RSA *private;
|
||||
private = RSA_generate_key(bits, 35, NULL, NULL);
|
||||
if (private == NULL)
|
||||
fatal("rsa_generate_private_key: key generation failed.");
|
||||
return private;
|
||||
}
|
||||
|
||||
DSA*
|
||||
dsa_generate_private_key(unsigned int bits)
|
||||
{
|
||||
DSA *private = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
|
||||
if (private == NULL)
|
||||
fatal("dsa_generate_private_key: DSA_generate_parameters failed");
|
||||
if (!DSA_generate_key(private))
|
||||
fatal("dsa_generate_private_key: DSA_generate_key failed.");
|
||||
if (private == NULL)
|
||||
fatal("dsa_generate_private_key: NULL.");
|
||||
return private;
|
||||
}
|
||||
|
||||
Key *
|
||||
key_generate(int type, unsigned int bits)
|
||||
{
|
||||
Key *k = key_new(KEY_UNSPEC);
|
||||
switch (type) {
|
||||
case KEY_DSA:
|
||||
k->dsa = dsa_generate_private_key(bits);
|
||||
break;
|
||||
case KEY_RSA:
|
||||
case KEY_RSA1:
|
||||
k->rsa = rsa_generate_private_key(bits);
|
||||
break;
|
||||
default:
|
||||
fatal("key_generate: unknown type %d", type);
|
||||
}
|
||||
k->type = type;
|
||||
return k;
|
||||
}
|
||||
|
||||
Key *
|
||||
key_from_private(Key *k)
|
||||
{
|
||||
Key *n = NULL;
|
||||
switch (k->type) {
|
||||
case KEY_DSA:
|
||||
n = key_new(k->type);
|
||||
BN_copy(n->dsa->p, k->dsa->p);
|
||||
BN_copy(n->dsa->q, k->dsa->q);
|
||||
BN_copy(n->dsa->g, k->dsa->g);
|
||||
BN_copy(n->dsa->pub_key, k->dsa->pub_key);
|
||||
break;
|
||||
case KEY_RSA:
|
||||
case KEY_RSA1:
|
||||
n = key_new(k->type);
|
||||
BN_copy(n->rsa->n, k->rsa->n);
|
||||
BN_copy(n->rsa->e, k->rsa->e);
|
||||
break;
|
||||
default:
|
||||
fatal("key_from_private: unknown type %d", k->type);
|
||||
break;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
key_type_from_name(char *name)
|
||||
{
|
||||
if (strcmp(name, "rsa1") == 0){
|
||||
return KEY_RSA1;
|
||||
} else if (strcmp(name, "rsa") == 0){
|
||||
return KEY_RSA;
|
||||
} else if (strcmp(name, "dsa") == 0){
|
||||
return KEY_DSA;
|
||||
} else if (strcmp(name, "ssh-rsa") == 0){
|
||||
return KEY_RSA;
|
||||
} else if (strcmp(name, "ssh-dss") == 0){
|
||||
return KEY_DSA;
|
||||
}
|
||||
debug("key_type_from_name: unknown key type '%s'", name);
|
||||
return KEY_UNSPEC;
|
||||
}
|
||||
|
||||
Key *
|
||||
key_from_blob(char *blob, int blen)
|
||||
{
|
||||
Buffer b;
|
||||
char *ktype;
|
||||
int rlen, type;
|
||||
Key *key = NULL;
|
||||
|
||||
#ifdef DEBUG_PK
|
||||
dump_base64(stderr, blob, blen);
|
||||
#endif
|
||||
buffer_init(&b);
|
||||
buffer_append(&b, blob, blen);
|
||||
ktype = buffer_get_string(&b, NULL);
|
||||
type = key_type_from_name(ktype);
|
||||
|
||||
switch(type){
|
||||
case KEY_RSA:
|
||||
key = key_new(type);
|
||||
buffer_get_bignum2(&b, key->rsa->n);
|
||||
buffer_get_bignum2(&b, key->rsa->e);
|
||||
#ifdef DEBUG_PK
|
||||
RSA_print_fp(stderr, key->rsa, 8);
|
||||
#endif
|
||||
break;
|
||||
case KEY_DSA:
|
||||
key = key_new(type);
|
||||
buffer_get_bignum2(&b, key->dsa->p);
|
||||
buffer_get_bignum2(&b, key->dsa->q);
|
||||
buffer_get_bignum2(&b, key->dsa->g);
|
||||
buffer_get_bignum2(&b, key->dsa->pub_key);
|
||||
#ifdef DEBUG_PK
|
||||
DSA_print_fp(stderr, key->dsa, 8);
|
||||
#endif
|
||||
break;
|
||||
case KEY_UNSPEC:
|
||||
key = key_new(type);
|
||||
break;
|
||||
default:
|
||||
error("key_from_blob: cannot handle type %s", ktype);
|
||||
break;
|
||||
}
|
||||
rlen = buffer_len(&b);
|
||||
if (key != NULL && rlen != 0)
|
||||
error("key_from_blob: remaining bytes in key blob %d", rlen);
|
||||
xfree(ktype);
|
||||
buffer_free(&b);
|
||||
return key;
|
||||
}
|
||||
|
||||
int
|
||||
key_to_blob(Key *key, unsigned char **blobp, unsigned int *lenp)
|
||||
{
|
||||
Buffer b;
|
||||
int len;
|
||||
unsigned char *buf;
|
||||
|
||||
if (key == NULL) {
|
||||
error("key_to_blob: key == NULL");
|
||||
return 0;
|
||||
}
|
||||
buffer_init(&b);
|
||||
switch(key->type){
|
||||
case KEY_DSA:
|
||||
buffer_put_cstring(&b, key_ssh_name(key));
|
||||
buffer_put_bignum2(&b, key->dsa->p);
|
||||
buffer_put_bignum2(&b, key->dsa->q);
|
||||
buffer_put_bignum2(&b, key->dsa->g);
|
||||
buffer_put_bignum2(&b, key->dsa->pub_key);
|
||||
break;
|
||||
case KEY_RSA:
|
||||
buffer_put_cstring(&b, key_ssh_name(key));
|
||||
buffer_put_bignum2(&b, key->rsa->n);
|
||||
buffer_put_bignum2(&b, key->rsa->e);
|
||||
break;
|
||||
default:
|
||||
error("key_to_blob: illegal key type %d", key->type);
|
||||
break;
|
||||
}
|
||||
len = buffer_len(&b);
|
||||
buf = xmalloc(len);
|
||||
memcpy(buf, buffer_ptr(&b), len);
|
||||
memset(buffer_ptr(&b), 0, len);
|
||||
buffer_free(&b);
|
||||
if (lenp != NULL)
|
||||
*lenp = len;
|
||||
if (blobp != NULL)
|
||||
*blobp = buf;
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
key_sign(
|
||||
Key *key,
|
||||
unsigned char **sigp, int *lenp,
|
||||
unsigned char *data, int datalen)
|
||||
{
|
||||
switch(key->type){
|
||||
case KEY_DSA:
|
||||
return ssh_dss_sign(key, sigp, lenp, data, datalen);
|
||||
break;
|
||||
case KEY_RSA:
|
||||
return ssh_rsa_sign(key, sigp, lenp, data, datalen);
|
||||
break;
|
||||
default:
|
||||
error("key_sign: illegal key type %d", key->type);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
key_verify(
|
||||
Key *key,
|
||||
unsigned char *signature, int signaturelen,
|
||||
unsigned char *data, int datalen)
|
||||
{
|
||||
switch(key->type){
|
||||
case KEY_DSA:
|
||||
return ssh_dss_verify(key, signature, signaturelen, data, datalen);
|
||||
break;
|
||||
case KEY_RSA:
|
||||
return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
|
||||
break;
|
||||
default:
|
||||
error("key_verify: illegal key type %d", key->type);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
28
key.h
28
key.h
|
@ -26,9 +26,10 @@
|
|||
|
||||
typedef struct Key Key;
|
||||
enum types {
|
||||
KEY_RSA1,
|
||||
KEY_RSA,
|
||||
KEY_DSA,
|
||||
KEY_EMPTY
|
||||
KEY_UNSPEC
|
||||
};
|
||||
struct Key {
|
||||
int type;
|
||||
|
@ -37,12 +38,33 @@ struct Key {
|
|||
};
|
||||
|
||||
Key *key_new(int type);
|
||||
Key *key_new_private(int type);
|
||||
void key_free(Key *k);
|
||||
int key_equal(Key *a, Key *b);
|
||||
char *key_fingerprint(Key *k);
|
||||
char *key_type(Key *k);
|
||||
int key_write(Key *key, FILE *f);
|
||||
unsigned int key_read(Key *key, char **cpp);
|
||||
unsigned int key_size(Key *k);
|
||||
int key_read(Key *key, char **cpp);
|
||||
u_int key_size(Key *k);
|
||||
|
||||
Key *key_generate(int type, unsigned int bits);
|
||||
Key *key_from_private(Key *k);
|
||||
int key_type_from_name(char *name);
|
||||
|
||||
Key *key_from_blob(char *blob, int blen);
|
||||
int key_to_blob(Key *key, unsigned char **blobp, unsigned int *lenp);
|
||||
char *key_ssh_name(Key *k);
|
||||
|
||||
int
|
||||
key_sign(
|
||||
Key *key,
|
||||
unsigned char **sigp, int *lenp,
|
||||
unsigned char *data, int datalen);
|
||||
|
||||
int
|
||||
key_verify(
|
||||
Key *key,
|
||||
unsigned char *signature, int signaturelen,
|
||||
unsigned char *data, int datalen);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#define KEX_DEFAULT_KEX "diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1"
|
||||
#define KEX_DEFAULT_PK_ALG "ssh-dss"
|
||||
#define KEX_DEFAULT_PK_ALG "ssh-rsa,ssh-dss"
|
||||
#define KEX_DEFAULT_ENCRYPT \
|
||||
"3des-cbc,blowfish-cbc,cast128-cbc,arcfour," \
|
||||
"aes128-cbc,aes192-cbc,aes256-cbc," \
|
||||
|
|
6
nchan.c
6
nchan.c
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: nchan.c,v 1.19 2000/09/07 20:27:52 deraadt Exp $");
|
||||
RCSID("$OpenBSD: nchan.c,v 1.20 2000/11/06 23:04:56 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
|
||||
|
@ -253,6 +253,8 @@ chan_send_oclose1(Channel *c)
|
|||
static void
|
||||
chan_delete_if_full_closed1(Channel *c)
|
||||
{
|
||||
debug3("channel %d: chan_delete_if_full_closed1: istate %d ostate %d",
|
||||
c->self, c->istate, c->ostate);
|
||||
if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
|
||||
debug("channel %d: full closed", c->self);
|
||||
channel_free(c->self);
|
||||
|
@ -403,6 +405,8 @@ chan_send_close2(Channel *c)
|
|||
static void
|
||||
chan_delete_if_full_closed2(Channel *c)
|
||||
{
|
||||
debug3("channel %d: chan_delete_if_full_closed2: istate %d ostate %d",
|
||||
c->self, c->istate, c->ostate);
|
||||
if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
|
||||
if (!(c->flags & CHAN_CLOSE_SENT)) {
|
||||
chan_send_close2(c);
|
||||
|
|
55
readconf.c
55
readconf.c
|
@ -12,7 +12,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: readconf.c,v 1.49 2000/10/11 20:27:23 markus Exp $");
|
||||
RCSID("$OpenBSD: readconf.c,v 1.50 2000/11/12 19:50:37 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "readconf.h"
|
||||
|
@ -68,7 +68,7 @@ RCSID("$OpenBSD: readconf.c,v 1.49 2000/10/11 20:27:23 markus Exp $");
|
|||
# Defaults for various options
|
||||
Host *
|
||||
ForwardAgent no
|
||||
ForwardX11 yes
|
||||
ForwardX11 no
|
||||
RhostsAuthentication yes
|
||||
PasswordAuthentication yes
|
||||
RSAAuthentication yes
|
||||
|
@ -101,8 +101,8 @@ typedef enum {
|
|||
oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
|
||||
oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
|
||||
oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
|
||||
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oIdentityFile2,
|
||||
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oDSAAuthentication,
|
||||
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol,
|
||||
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
|
||||
oKbdInteractiveAuthentication, oKbdInteractiveDevices
|
||||
} OpCodes;
|
||||
|
||||
|
@ -122,7 +122,8 @@ static struct {
|
|||
{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
|
||||
{ "kbdinteractivedevices", oKbdInteractiveDevices },
|
||||
{ "rsaauthentication", oRSAAuthentication },
|
||||
{ "dsaauthentication", oDSAAuthentication },
|
||||
{ "pubkeyauthentication", oPubkeyAuthentication },
|
||||
{ "dsaauthentication", oPubkeyAuthentication }, /* alias */
|
||||
{ "skeyauthentication", oSkeyAuthentication },
|
||||
#ifdef KRB4
|
||||
{ "kerberosauthentication", oKerberosAuthentication },
|
||||
|
@ -134,7 +135,7 @@ static struct {
|
|||
{ "fallbacktorsh", oFallBackToRsh },
|
||||
{ "usersh", oUseRsh },
|
||||
{ "identityfile", oIdentityFile },
|
||||
{ "identityfile2", oIdentityFile2 },
|
||||
{ "identityfile2", oIdentityFile }, /* alias */
|
||||
{ "hostname", oHostName },
|
||||
{ "proxycommand", oProxyCommand },
|
||||
{ "port", oPort },
|
||||
|
@ -300,8 +301,8 @@ parse_flag:
|
|||
charptr = &options->kbd_interactive_devices;
|
||||
goto parse_string;
|
||||
|
||||
case oDSAAuthentication:
|
||||
intptr = &options->dsa_authentication;
|
||||
case oPubkeyAuthentication:
|
||||
intptr = &options->pubkey_authentication;
|
||||
goto parse_flag;
|
||||
|
||||
case oRSAAuthentication:
|
||||
|
@ -386,20 +387,15 @@ parse_flag:
|
|||
goto parse_int;
|
||||
|
||||
case oIdentityFile:
|
||||
case oIdentityFile2:
|
||||
arg = strdelim(&s);
|
||||
if (!arg || *arg == '\0')
|
||||
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
||||
if (*activep) {
|
||||
intptr = (opcode == oIdentityFile) ?
|
||||
&options->num_identity_files :
|
||||
&options->num_identity_files2;
|
||||
intptr = &options->num_identity_files;
|
||||
if (*intptr >= SSH_MAX_IDENTITY_FILES)
|
||||
fatal("%.200s line %d: Too many identity files specified (max %d).",
|
||||
filename, linenum, SSH_MAX_IDENTITY_FILES);
|
||||
charptr = (opcode == oIdentityFile) ?
|
||||
&options->identity_files[*intptr] :
|
||||
&options->identity_files2[*intptr];
|
||||
charptr = &options->identity_files[*intptr];
|
||||
*charptr = xstrdup(arg);
|
||||
*intptr = *intptr + 1;
|
||||
}
|
||||
|
@ -664,7 +660,7 @@ initialize_options(Options * options)
|
|||
options->use_privileged_port = -1;
|
||||
options->rhosts_authentication = -1;
|
||||
options->rsa_authentication = -1;
|
||||
options->dsa_authentication = -1;
|
||||
options->pubkey_authentication = -1;
|
||||
options->skey_authentication = -1;
|
||||
#ifdef KRB4
|
||||
options->kerberos_authentication = -1;
|
||||
|
@ -692,7 +688,6 @@ initialize_options(Options * options)
|
|||
options->ciphers = NULL;
|
||||
options->protocol = SSH_PROTO_UNKNOWN;
|
||||
options->num_identity_files = 0;
|
||||
options->num_identity_files2 = 0;
|
||||
options->hostname = NULL;
|
||||
options->proxy_command = NULL;
|
||||
options->user = NULL;
|
||||
|
@ -730,8 +725,8 @@ fill_default_options(Options * options)
|
|||
options->rhosts_authentication = 1;
|
||||
if (options->rsa_authentication == -1)
|
||||
options->rsa_authentication = 1;
|
||||
if (options->dsa_authentication == -1)
|
||||
options->dsa_authentication = 1;
|
||||
if (options->pubkey_authentication == -1)
|
||||
options->pubkey_authentication = 1;
|
||||
if (options->skey_authentication == -1)
|
||||
options->skey_authentication = 0;
|
||||
#ifdef KRB4
|
||||
|
@ -779,16 +774,18 @@ fill_default_options(Options * options)
|
|||
if (options->protocol == SSH_PROTO_UNKNOWN)
|
||||
options->protocol = SSH_PROTO_1|SSH_PROTO_2|SSH_PROTO_1_PREFERRED;
|
||||
if (options->num_identity_files == 0) {
|
||||
options->identity_files[0] =
|
||||
xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
|
||||
sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
|
||||
options->num_identity_files = 1;
|
||||
}
|
||||
if (options->num_identity_files2 == 0) {
|
||||
options->identity_files2[0] =
|
||||
xmalloc(2 + strlen(SSH_CLIENT_ID_DSA) + 1);
|
||||
sprintf(options->identity_files2[0], "~/%.100s", SSH_CLIENT_ID_DSA);
|
||||
options->num_identity_files2 = 1;
|
||||
if (options->protocol & SSH_PROTO_1) {
|
||||
options->identity_files[options->num_identity_files] =
|
||||
xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
|
||||
sprintf(options->identity_files[options->num_identity_files++],
|
||||
"~/%.100s", SSH_CLIENT_IDENTITY);
|
||||
}
|
||||
if (options->protocol & SSH_PROTO_2) {
|
||||
options->identity_files[options->num_identity_files] =
|
||||
xmalloc(2 + strlen(SSH_CLIENT_ID_DSA) + 1);
|
||||
sprintf(options->identity_files[options->num_identity_files++],
|
||||
"~/%.100s", SSH_CLIENT_ID_DSA);
|
||||
}
|
||||
}
|
||||
if (options->escape_char == -1)
|
||||
options->escape_char = '~';
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*/
|
||||
|
||||
/* RCSID("$OpenBSD: readconf.h,v 1.22 2000/10/11 20:14:39 markus Exp $"); */
|
||||
/* RCSID("$OpenBSD: readconf.h,v 1.23 2000/11/12 19:50:37 markus Exp $"); */
|
||||
|
||||
#ifndef READCONF_H
|
||||
#define READCONF_H
|
||||
|
@ -35,7 +35,7 @@ typedef struct {
|
|||
int rhosts_rsa_authentication; /* Try rhosts with RSA
|
||||
* authentication. */
|
||||
int rsa_authentication; /* Try RSA authentication. */
|
||||
int dsa_authentication; /* Try DSA authentication. */
|
||||
int pubkey_authentication; /* Try ssh2 pubkey authentication. */
|
||||
int skey_authentication; /* Try S/Key or TIS authentication. */
|
||||
#ifdef KRB4
|
||||
int kerberos_authentication; /* Try Kerberos
|
||||
|
@ -78,10 +78,9 @@ typedef struct {
|
|||
char *system_hostfile2;
|
||||
char *user_hostfile2;
|
||||
|
||||
int num_identity_files; /* Number of files for RSA identities. */
|
||||
int num_identity_files2; /* DSA identities. */
|
||||
int num_identity_files; /* Number of files for RSA/DSA identities. */
|
||||
char *identity_files[SSH_MAX_IDENTITY_FILES];
|
||||
char *identity_files2[SSH_MAX_IDENTITY_FILES];
|
||||
int identity_files_type[SSH_MAX_IDENTITY_FILES];
|
||||
|
||||
/* Local TCP/IP forward requests. */
|
||||
int num_local_forwards;
|
||||
|
|
79
rsa.c
79
rsa.c
|
@ -60,82 +60,13 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: rsa.c,v 1.16 2000/09/07 20:27:53 deraadt Exp $");
|
||||
RCSID("$OpenBSD: rsa.c,v 1.17 2000/11/12 19:50:37 markus Exp $");
|
||||
|
||||
#include "rsa.h"
|
||||
#include "ssh.h"
|
||||
#include "xmalloc.h"
|
||||
#include "entropy.h"
|
||||
|
||||
int rsa_verbose = 1;
|
||||
|
||||
int
|
||||
rsa_alive()
|
||||
{
|
||||
RSA *key;
|
||||
|
||||
seed_rng();
|
||||
key = RSA_generate_key(32, 3, NULL, NULL);
|
||||
if (key == NULL)
|
||||
return (0);
|
||||
RSA_free(key);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates RSA public and private keys. This initializes the data
|
||||
* structures; they should be freed with rsa_clear_private_key and
|
||||
* rsa_clear_public_key.
|
||||
*/
|
||||
|
||||
void
|
||||
rsa_generate_key(RSA *prv, RSA *pub, unsigned int bits)
|
||||
{
|
||||
RSA *key;
|
||||
|
||||
seed_rng();
|
||||
|
||||
if (rsa_verbose) {
|
||||
printf("Generating RSA keys: ");
|
||||
fflush(stdout);
|
||||
}
|
||||
key = RSA_generate_key(bits, 35, NULL, NULL);
|
||||
if (key == NULL)
|
||||
fatal("rsa_generate_key: key generation failed.");
|
||||
|
||||
/* Copy public key parameters */
|
||||
pub->n = BN_new();
|
||||
BN_copy(pub->n, key->n);
|
||||
pub->e = BN_new();
|
||||
BN_copy(pub->e, key->e);
|
||||
|
||||
/* Copy private key parameters */
|
||||
prv->n = BN_new();
|
||||
BN_copy(prv->n, key->n);
|
||||
prv->e = BN_new();
|
||||
BN_copy(prv->e, key->e);
|
||||
prv->d = BN_new();
|
||||
BN_copy(prv->d, key->d);
|
||||
prv->p = BN_new();
|
||||
BN_copy(prv->p, key->p);
|
||||
prv->q = BN_new();
|
||||
BN_copy(prv->q, key->q);
|
||||
|
||||
prv->dmp1 = BN_new();
|
||||
BN_copy(prv->dmp1, key->dmp1);
|
||||
|
||||
prv->dmq1 = BN_new();
|
||||
BN_copy(prv->dmq1, key->dmq1);
|
||||
|
||||
prv->iqmp = BN_new();
|
||||
BN_copy(prv->iqmp, key->iqmp);
|
||||
|
||||
RSA_free(key);
|
||||
|
||||
if (rsa_verbose)
|
||||
printf("Key generation complete.\n");
|
||||
}
|
||||
|
||||
void
|
||||
rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
||||
{
|
||||
|
@ -188,11 +119,3 @@ rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
|||
xfree(outbuf);
|
||||
xfree(inbuf);
|
||||
}
|
||||
|
||||
/* Set whether to output verbose messages during key generation. */
|
||||
|
||||
void
|
||||
rsa_set_verbose(int verbose)
|
||||
{
|
||||
rsa_verbose = verbose;
|
||||
}
|
||||
|
|
13
rsa.h
13
rsa.h
|
@ -11,7 +11,7 @@
|
|||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*/
|
||||
|
||||
/* RCSID("$OpenBSD: rsa.h,v 1.8 2000/09/07 20:27:53 deraadt Exp $"); */
|
||||
/* RCSID("$OpenBSD: rsa.h,v 1.9 2000/11/12 19:50:38 markus Exp $"); */
|
||||
|
||||
#ifndef RSA_H
|
||||
#define RSA_H
|
||||
|
@ -19,17 +19,6 @@
|
|||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
/* Calls SSL RSA_generate_key, only copies to prv and pub */
|
||||
void rsa_generate_key(RSA * prv, RSA * pub, unsigned int bits);
|
||||
|
||||
/*
|
||||
* Indicates whether the rsa module is permitted to show messages on the
|
||||
* terminal.
|
||||
*/
|
||||
void rsa_set_verbose __P((int verbose));
|
||||
|
||||
int rsa_alive __P((void));
|
||||
|
||||
void rsa_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
|
||||
void rsa_private_decrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
|
||||
|
||||
|
|
57
servconf.c
57
servconf.c
|
@ -10,7 +10,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: servconf.c,v 1.53 2000/10/14 12:12:09 markus Exp $");
|
||||
RCSID("$OpenBSD: servconf.c,v 1.54 2000/11/12 19:50:38 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "servconf.h"
|
||||
|
@ -29,8 +29,7 @@ initialize_server_options(ServerOptions *options)
|
|||
options->num_ports = 0;
|
||||
options->ports_from_cmdline = 0;
|
||||
options->listen_addrs = NULL;
|
||||
options->host_key_file = NULL;
|
||||
options->host_dsa_key_file = NULL;
|
||||
options->num_host_key_files = 0;
|
||||
options->pid_file = NULL;
|
||||
options->server_key_bits = -1;
|
||||
options->login_grace_time = -1;
|
||||
|
@ -50,7 +49,7 @@ initialize_server_options(ServerOptions *options)
|
|||
options->rhosts_authentication = -1;
|
||||
options->rhosts_rsa_authentication = -1;
|
||||
options->rsa_authentication = -1;
|
||||
options->dsa_authentication = -1;
|
||||
options->pubkey_authentication = -1;
|
||||
#ifdef KRB4
|
||||
options->kerberos_authentication = -1;
|
||||
options->kerberos_or_local_passwd = -1;
|
||||
|
@ -84,14 +83,19 @@ initialize_server_options(ServerOptions *options)
|
|||
void
|
||||
fill_default_server_options(ServerOptions *options)
|
||||
{
|
||||
if (options->protocol == SSH_PROTO_UNKNOWN)
|
||||
options->protocol = SSH_PROTO_1|SSH_PROTO_2;
|
||||
if (options->num_host_key_files == 0) {
|
||||
/* fill default hostkeys for protocols */
|
||||
if (options->protocol & SSH_PROTO_1)
|
||||
options->host_key_files[options->num_host_key_files++] = HOST_KEY_FILE;
|
||||
if (options->protocol & SSH_PROTO_2)
|
||||
options->host_key_files[options->num_host_key_files++] = HOST_DSA_KEY_FILE;
|
||||
}
|
||||
if (options->num_ports == 0)
|
||||
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
|
||||
if (options->listen_addrs == NULL)
|
||||
add_listen_addr(options, NULL);
|
||||
if (options->host_key_file == NULL)
|
||||
options->host_key_file = HOST_KEY_FILE;
|
||||
if (options->host_dsa_key_file == NULL)
|
||||
options->host_dsa_key_file = HOST_DSA_KEY_FILE;
|
||||
if (options->pid_file == NULL)
|
||||
options->pid_file = SSH_DAEMON_PID_FILE;
|
||||
if (options->server_key_bits == -1)
|
||||
|
@ -132,8 +136,8 @@ fill_default_server_options(ServerOptions *options)
|
|||
options->rhosts_rsa_authentication = 0;
|
||||
if (options->rsa_authentication == -1)
|
||||
options->rsa_authentication = 1;
|
||||
if (options->dsa_authentication == -1)
|
||||
options->dsa_authentication = 1;
|
||||
if (options->pubkey_authentication == -1)
|
||||
options->pubkey_authentication = 1;
|
||||
#ifdef KRB4
|
||||
if (options->kerberos_authentication == -1)
|
||||
options->kerberos_authentication = (access(KEYFILE, R_OK) == 0);
|
||||
|
@ -162,8 +166,6 @@ fill_default_server_options(ServerOptions *options)
|
|||
options->use_login = 0;
|
||||
if (options->allow_tcp_forwarding == -1)
|
||||
options->allow_tcp_forwarding = 1;
|
||||
if (options->protocol == SSH_PROTO_UNKNOWN)
|
||||
options->protocol = SSH_PROTO_1|SSH_PROTO_2;
|
||||
if (options->gateway_ports == -1)
|
||||
options->gateway_ports = 0;
|
||||
if (options->max_startups == -1)
|
||||
|
@ -194,8 +196,8 @@ typedef enum {
|
|||
sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
|
||||
sUseLogin, sAllowTcpForwarding,
|
||||
sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
|
||||
sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile,
|
||||
sGatewayPorts, sDSAAuthentication, sXAuthLocation, sSubsystem, sMaxStartups
|
||||
sIgnoreUserKnownHosts, sCiphers, sProtocol, sPidFile,
|
||||
sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
|
||||
} ServerOpCodes;
|
||||
|
||||
/* Textual representation of the tokens. */
|
||||
|
@ -205,7 +207,7 @@ static struct {
|
|||
} keywords[] = {
|
||||
{ "port", sPort },
|
||||
{ "hostkey", sHostKeyFile },
|
||||
{ "hostdsakey", sHostDSAKeyFile },
|
||||
{ "hostdsakey", sHostKeyFile }, /* alias */
|
||||
{ "pidfile", sPidFile },
|
||||
{ "serverkeybits", sServerKeyBits },
|
||||
{ "logingracetime", sLoginGraceTime },
|
||||
|
@ -216,7 +218,8 @@ static struct {
|
|||
{ "rhostsauthentication", sRhostsAuthentication },
|
||||
{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
|
||||
{ "rsaauthentication", sRSAAuthentication },
|
||||
{ "dsaauthentication", sDSAAuthentication },
|
||||
{ "pubkeyauthentication", sPubkeyAuthentication },
|
||||
{ "dsaauthentication", sPubkeyAuthentication }, /* alias */
|
||||
#ifdef KRB4
|
||||
{ "kerberosauthentication", sKerberosAuthentication },
|
||||
{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
|
||||
|
@ -336,6 +339,8 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||
arg = strdelim(&cp);
|
||||
if (!*arg || *arg == '#')
|
||||
continue;
|
||||
intptr = NULL;
|
||||
charptr = NULL;
|
||||
opcode = parse_token(arg, filename, linenum);
|
||||
switch (opcode) {
|
||||
case sBadOption:
|
||||
|
@ -389,9 +394,13 @@ parse_int:
|
|||
break;
|
||||
|
||||
case sHostKeyFile:
|
||||
case sHostDSAKeyFile:
|
||||
charptr = (opcode == sHostKeyFile ) ?
|
||||
&options->host_key_file : &options->host_dsa_key_file;
|
||||
intptr = &options->num_host_key_files;
|
||||
if (*intptr >= MAX_HOSTKEYS) {
|
||||
fprintf(stderr, "%s line %d: to many host keys specified (max %d).\n",
|
||||
filename, linenum, MAX_HOSTKEYS);
|
||||
exit(1);
|
||||
}
|
||||
charptr = &options->host_key_files[*intptr];
|
||||
parse_filename:
|
||||
arg = strdelim(&cp);
|
||||
if (!arg || *arg == '\0') {
|
||||
|
@ -399,8 +408,12 @@ parse_filename:
|
|||
filename, linenum);
|
||||
exit(1);
|
||||
}
|
||||
if (*charptr == NULL)
|
||||
if (*charptr == NULL) {
|
||||
*charptr = tilde_expand_filename(arg, getuid());
|
||||
/* increase optional counter */
|
||||
if (intptr != NULL)
|
||||
*intptr = *intptr + 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case sPidFile:
|
||||
|
@ -474,8 +487,8 @@ parse_flag:
|
|||
intptr = &options->rsa_authentication;
|
||||
goto parse_flag;
|
||||
|
||||
case sDSAAuthentication:
|
||||
intptr = &options->dsa_authentication;
|
||||
case sPubkeyAuthentication:
|
||||
intptr = &options->pubkey_authentication;
|
||||
goto parse_flag;
|
||||
|
||||
#ifdef KRB4
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
* called by a name other than "ssh" or "Secure Shell".
|
||||
*/
|
||||
|
||||
/* RCSID("$OpenBSD: servconf.h,v 1.30 2000/10/14 12:12:09 markus Exp $"); */
|
||||
/* RCSID("$OpenBSD: servconf.h,v 1.31 2000/11/12 19:50:38 markus Exp $"); */
|
||||
|
||||
#ifndef SERVCONF_H
|
||||
#define SERVCONF_H
|
||||
|
@ -23,6 +23,7 @@
|
|||
#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */
|
||||
#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
|
||||
#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */
|
||||
#define MAX_HOSTKEYS 256 /* Max # hostkeys. */
|
||||
|
||||
typedef struct {
|
||||
unsigned int num_ports;
|
||||
|
@ -30,8 +31,8 @@ typedef struct {
|
|||
u_short ports[MAX_PORTS]; /* Port number to listen on. */
|
||||
char *listen_addr; /* Address on which the server listens. */
|
||||
struct addrinfo *listen_addrs; /* Addresses on which the server listens. */
|
||||
char *host_key_file; /* File containing host key. */
|
||||
char *host_dsa_key_file; /* File containing dsa host key. */
|
||||
char *host_key_files[MAX_HOSTKEYS]; /* Files containing host keys. */
|
||||
int num_host_key_files; /* Number of files for host keys. */
|
||||
char *pid_file; /* Where to put our pid */
|
||||
int server_key_bits;/* Size of the server key. */
|
||||
int login_grace_time; /* Disconnect if no auth in this time
|
||||
|
@ -59,7 +60,7 @@ typedef struct {
|
|||
int rhosts_rsa_authentication; /* If true, permit rhosts RSA
|
||||
* authentication. */
|
||||
int rsa_authentication; /* If true, permit RSA authentication. */
|
||||
int dsa_authentication; /* If true, permit DSA authentication. */
|
||||
int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */
|
||||
#ifdef KRB4
|
||||
int kerberos_authentication; /* If true, permit Kerberos
|
||||
* authentication. */
|
||||
|
|
128
serverloop.c
128
serverloop.c
|
@ -35,7 +35,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: serverloop.c,v 1.34 2000/10/27 07:32:18 markus Exp $");
|
||||
RCSID("$OpenBSD: serverloop.c,v 1.35 2000/11/06 23:04:56 markus Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
|
@ -50,6 +50,7 @@ RCSID("$OpenBSD: serverloop.c,v 1.34 2000/10/27 07:32:18 markus Exp $");
|
|||
#include "session.h"
|
||||
#include "dispatch.h"
|
||||
#include "auth-options.h"
|
||||
#include "auth.h"
|
||||
|
||||
extern ServerOptions options;
|
||||
|
||||
|
@ -739,10 +740,10 @@ server_input_window_size(int type, int plen, void *ctxt)
|
|||
pty_change_window_size(fdin, row, col, xpixel, ypixel);
|
||||
}
|
||||
|
||||
int
|
||||
input_direct_tcpip(void)
|
||||
Channel *
|
||||
server_request_direct_tcpip(char *ctype)
|
||||
{
|
||||
int sock;
|
||||
int sock, newch;
|
||||
char *target, *originator;
|
||||
int target_port, originator_port;
|
||||
|
||||
|
@ -752,23 +753,52 @@ input_direct_tcpip(void)
|
|||
originator_port = packet_get_int();
|
||||
packet_done();
|
||||
|
||||
debug("open direct-tcpip: from %s port %d to %s port %d",
|
||||
debug("server_request_direct_tcpip: originator %s port %d, target %s port %d",
|
||||
originator, originator_port, target, target_port);
|
||||
|
||||
/* XXX check permission */
|
||||
if (no_port_forwarding_flag || !options.allow_tcp_forwarding) {
|
||||
xfree(target);
|
||||
xfree(originator);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
sock = channel_connect_to(target, target_port);
|
||||
xfree(target);
|
||||
xfree(originator);
|
||||
if (sock < 0)
|
||||
return -1;
|
||||
return channel_new("direct-tcpip", SSH_CHANNEL_OPEN,
|
||||
return NULL;
|
||||
newch = channel_new(ctype, SSH_CHANNEL_OPEN,
|
||||
sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT,
|
||||
CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"), 1);
|
||||
return (newch >= 0) ? channel_lookup(newch) : NULL;
|
||||
}
|
||||
|
||||
Channel *
|
||||
server_request_session(char *ctype)
|
||||
{
|
||||
int newch;
|
||||
|
||||
debug("input_session_request");
|
||||
packet_done();
|
||||
/*
|
||||
* A server session has no fd to read or write until a
|
||||
* CHANNEL_REQUEST for a shell is made, so we set the type to
|
||||
* SSH_CHANNEL_LARVAL. Additionally, a callback for handling all
|
||||
* CHANNEL_REQUEST messages is registered.
|
||||
*/
|
||||
newch = channel_new(ctype, SSH_CHANNEL_LARVAL,
|
||||
-1, -1, -1, 0, CHAN_SES_PACKET_DEFAULT,
|
||||
0, xstrdup("server-session"), 1);
|
||||
if (session_open(newch) == 1) {
|
||||
channel_register_callback(newch, SSH2_MSG_CHANNEL_REQUEST,
|
||||
session_input_channel_req, (void *)0);
|
||||
channel_register_cleanup(newch, session_close_by_channel);
|
||||
return channel_lookup(newch);
|
||||
} else {
|
||||
debug("session open failed, free channel %d", newch);
|
||||
channel_free(newch);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -776,7 +806,6 @@ server_input_channel_open(int type, int plen, void *ctxt)
|
|||
{
|
||||
Channel *c = NULL;
|
||||
char *ctype;
|
||||
int id;
|
||||
unsigned int len;
|
||||
int rchan;
|
||||
int rmaxpack;
|
||||
|
@ -791,34 +820,12 @@ server_input_channel_open(int type, int plen, void *ctxt)
|
|||
ctype, rchan, rwindow, rmaxpack);
|
||||
|
||||
if (strcmp(ctype, "session") == 0) {
|
||||
debug("open session");
|
||||
packet_done();
|
||||
/*
|
||||
* A server session has no fd to read or write
|
||||
* until a CHANNEL_REQUEST for a shell is made,
|
||||
* so we set the type to SSH_CHANNEL_LARVAL.
|
||||
* Additionally, a callback for handling all
|
||||
* CHANNEL_REQUEST messages is registered.
|
||||
*/
|
||||
id = channel_new(ctype, SSH_CHANNEL_LARVAL,
|
||||
-1, -1, -1, 0, CHAN_SES_PACKET_DEFAULT,
|
||||
0, xstrdup("server-session"), 1);
|
||||
if (session_open(id) == 1) {
|
||||
channel_register_callback(id, SSH2_MSG_CHANNEL_REQUEST,
|
||||
session_input_channel_req, (void *)0);
|
||||
channel_register_cleanup(id, session_close_by_channel);
|
||||
c = channel_lookup(id);
|
||||
} else {
|
||||
debug("session open failed, free channel %d", id);
|
||||
channel_free(id);
|
||||
}
|
||||
c = server_request_session(ctype);
|
||||
} else if (strcmp(ctype, "direct-tcpip") == 0) {
|
||||
id = input_direct_tcpip();
|
||||
if (id >= 0)
|
||||
c = channel_lookup(id);
|
||||
c = server_request_direct_tcpip(ctype);
|
||||
}
|
||||
if (c != NULL) {
|
||||
debug("confirm %s", ctype);
|
||||
debug("server_input_channel_open: confirm %s", ctype);
|
||||
c->remote_id = rchan;
|
||||
c->remote_window = rwindow;
|
||||
c->remote_maxpacket = rmaxpack;
|
||||
|
@ -830,7 +837,7 @@ server_input_channel_open(int type, int plen, void *ctxt)
|
|||
packet_put_int(c->local_maxpacket);
|
||||
packet_send();
|
||||
} else {
|
||||
debug("failure %s", ctype);
|
||||
debug("server_input_channel_open: failure %s", ctype);
|
||||
packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
|
||||
packet_put_int(rchan);
|
||||
packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
|
||||
|
@ -841,6 +848,56 @@ server_input_channel_open(int type, int plen, void *ctxt)
|
|||
xfree(ctype);
|
||||
}
|
||||
|
||||
void
|
||||
server_input_global_request(int type, int plen, void *ctxt)
|
||||
{
|
||||
char *rtype;
|
||||
int want_reply;
|
||||
int success = 0;
|
||||
|
||||
rtype = packet_get_string(NULL);
|
||||
want_reply = packet_get_char();
|
||||
debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply);
|
||||
|
||||
if (strcmp(rtype, "tcpip-forward") == 0) {
|
||||
struct passwd *pw;
|
||||
char *listen_address;
|
||||
u_short listen_port;
|
||||
|
||||
pw = auth_get_user();
|
||||
if (pw == NULL)
|
||||
fatal("server_input_global_request: no user");
|
||||
listen_address = packet_get_string(NULL); /* XXX currently ignored */
|
||||
listen_port = (u_short)packet_get_int();
|
||||
debug("server_input_global_request: tcpip-forward listen %s port %d",
|
||||
listen_address, listen_port);
|
||||
|
||||
/* check permissions */
|
||||
if (!options.allow_tcp_forwarding ||
|
||||
no_port_forwarding_flag ||
|
||||
(listen_port < IPPORT_RESERVED && pw->pw_uid != 0)) {
|
||||
success = 0;
|
||||
packet_send_debug("Server has disabled port forwarding.");
|
||||
} else {
|
||||
/* Start listening on the port */
|
||||
channel_request_forwarding(
|
||||
listen_address, listen_port,
|
||||
/*unspec host_to_connect*/ "<unspec host>",
|
||||
/*unspec port_to_connect*/ 0,
|
||||
options.gateway_ports, /*remote*/ 1);
|
||||
success = 1;
|
||||
}
|
||||
xfree(listen_address);
|
||||
}
|
||||
if (want_reply) {
|
||||
packet_start(success ?
|
||||
SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
|
||||
packet_send();
|
||||
packet_write_wait();
|
||||
}
|
||||
xfree(rtype);
|
||||
}
|
||||
|
||||
void
|
||||
server_init_dispatch_20()
|
||||
{
|
||||
|
@ -855,6 +912,7 @@ server_init_dispatch_20()
|
|||
dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
|
||||
dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request);
|
||||
dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
|
||||
dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
|
||||
}
|
||||
void
|
||||
server_init_dispatch_13()
|
||||
|
|
17
session.c
17
session.c
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: session.c,v 1.42 2000/10/27 07:32:18 markus Exp $");
|
||||
RCSID("$OpenBSD: session.c,v 1.43 2000/11/06 23:04:56 markus Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
|
@ -1735,6 +1735,19 @@ session_exec_req(Session *s)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
session_auth_agent_req(Session *s)
|
||||
{
|
||||
static int called = 0;
|
||||
packet_done();
|
||||
if (called) {
|
||||
return 0;
|
||||
} else {
|
||||
called = 1;
|
||||
return auth_input_request_forwarding(s->pw);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
session_input_channel_req(int id, void *arg)
|
||||
{
|
||||
|
@ -1771,6 +1784,8 @@ session_input_channel_req(int id, void *arg)
|
|||
success = session_pty_req(s);
|
||||
} else if (strcmp(rtype, "x11-req") == 0) {
|
||||
success = session_x11_req(s);
|
||||
} else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) {
|
||||
success = session_auth_agent_req(s);
|
||||
} else if (strcmp(rtype, "subsystem") == 0) {
|
||||
success = session_subsystem_req(s);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" $OpenBSD: sftp-server.8,v 1.3 2000/10/13 17:20:44 aaron Exp $
|
||||
.\" $OpenBSD: sftp-server.8,v 1.4 2000/11/10 05:10:40 aaron Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
.\"
|
||||
|
@ -48,7 +48,7 @@ for more information.
|
|||
.Xr ssh-add 1 ,
|
||||
.Xr ssh-keygen 1 ,
|
||||
.Xr sshd 8
|
||||
.Sh AUTHOR
|
||||
.Sh AUTHORS
|
||||
Markus Friedl <markus@openbsd.org>
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
|
|
|
@ -116,7 +116,7 @@ may be necessary to redirect the input from
|
|||
.Pa /dev/null
|
||||
to make this work.)
|
||||
.El
|
||||
.Sh AUTHOR
|
||||
.Sh AUTHORS
|
||||
Tatu Ylonen <ylo@cs.hut.fi>
|
||||
.Pp
|
||||
OpenSSH
|
||||
|
|
26
ssh-add.c
26
ssh-add.c
|
@ -35,7 +35,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: ssh-add.c,v 1.22 2000/09/07 20:27:54 deraadt Exp $");
|
||||
RCSID("$OpenBSD: ssh-add.c,v 1.23 2000/11/12 19:50:38 markus Exp $");
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
@ -60,10 +60,10 @@ delete_file(AuthenticationConnection *ac, const char *filename)
|
|||
Key *public;
|
||||
char *comment;
|
||||
|
||||
public = key_new(KEY_RSA);
|
||||
public = key_new(KEY_RSA1);
|
||||
if (!load_public_key(filename, public, &comment)) {
|
||||
key_free(public);
|
||||
public = key_new(KEY_DSA);
|
||||
public = key_new(KEY_UNSPEC);
|
||||
if (!try_load_public_key(filename, public, &comment)) {
|
||||
printf("Bad key file %s\n", filename);
|
||||
return;
|
||||
|
@ -144,7 +144,7 @@ add_file(AuthenticationConnection *ac, const char *filename)
|
|||
char buf[1024], msg[1024];
|
||||
int success;
|
||||
int interactive = isatty(STDIN_FILENO);
|
||||
int type = KEY_RSA;
|
||||
int type = KEY_RSA1;
|
||||
|
||||
if (stat(filename, &st) < 0) {
|
||||
perror(filename);
|
||||
|
@ -154,10 +154,10 @@ add_file(AuthenticationConnection *ac, const char *filename)
|
|||
* try to load the public key. right now this only works for RSA,
|
||||
* since DSA keys are fully encrypted
|
||||
*/
|
||||
public = key_new(KEY_RSA);
|
||||
public = key_new(KEY_RSA1);
|
||||
if (!load_public_key(filename, public, &saved_comment)) {
|
||||
/* ok, so we will asume this is a DSA key */
|
||||
type = KEY_DSA;
|
||||
/* ok, so we will assume this is 'some' key */
|
||||
type = KEY_UNSPEC;
|
||||
saved_comment = xstrdup(filename);
|
||||
}
|
||||
key_free(public);
|
||||
|
@ -223,8 +223,9 @@ list_identities(AuthenticationConnection *ac, int fp)
|
|||
key = ssh_get_next_identity(ac, &comment, version)) {
|
||||
had_identities = 1;
|
||||
if (fp) {
|
||||
printf("%d %s %s\n",
|
||||
key_size(key), key_fingerprint(key), comment);
|
||||
printf("%d %s %s (%s)\n",
|
||||
key_size(key), key_fingerprint(key),
|
||||
comment, key_type(key));
|
||||
} else {
|
||||
if (!key_write(key, stdout))
|
||||
fprintf(stderr, "key_write failed");
|
||||
|
@ -250,13 +251,6 @@ main(int argc, char **argv)
|
|||
|
||||
init_rng();
|
||||
|
||||
/* check if RSA support exists */
|
||||
if (rsa_alive() == 0) {
|
||||
fprintf(stderr,
|
||||
"%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
|
||||
__progname);
|
||||
exit(1);
|
||||
}
|
||||
SSLeay_add_all_algorithms();
|
||||
|
||||
/* At first, get a connection to the authentication agent. */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.\" $OpenBSD: ssh-agent.1,v 1.16 2000/09/07 20:27:54 deraadt Exp $
|
||||
.\" $OpenBSD: ssh-agent.1,v 1.17 2000/11/10 05:10:40 aaron Exp $
|
||||
.\"
|
||||
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
|
@ -160,7 +160,7 @@ authentication agent.
|
|||
These sockets should only be readable by the owner.
|
||||
The sockets should get automatically removed when the agent exits.
|
||||
.El
|
||||
.Sh AUTHOR
|
||||
.Sh AUTHORS
|
||||
Tatu Ylonen <ylo@cs.hut.fi>
|
||||
.Pp
|
||||
OpenSSH
|
||||
|
|
143
ssh-agent.c
143
ssh-agent.c
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: ssh-agent.c,v 1.37 2000/09/21 11:07:51 markus Exp $ */
|
||||
/* $OpenBSD: ssh-agent.c,v 1.39 2000/11/12 19:50:38 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: ssh-agent.c,v 1.37 2000/09/21 11:07:51 markus Exp $");
|
||||
RCSID("$OpenBSD: ssh-agent.c,v 1.39 2000/11/12 19:50:38 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "rsa.h"
|
||||
|
@ -54,7 +54,6 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.37 2000/09/21 11:07:51 markus Exp $");
|
|||
#include <openssl/rsa.h>
|
||||
#include "key.h"
|
||||
#include "authfd.h"
|
||||
#include "dsa.h"
|
||||
#include "kex.h"
|
||||
#include "compat.h"
|
||||
|
||||
|
@ -147,14 +146,14 @@ process_request_identities(SocketEntry *e, int version)
|
|||
buffer_put_int(&msg, tab->nentries);
|
||||
for (i = 0; i < tab->nentries; i++) {
|
||||
Identity *id = &tab->identities[i];
|
||||
if (id->key->type == KEY_RSA) {
|
||||
if (id->key->type == KEY_RSA1) {
|
||||
buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
|
||||
buffer_put_bignum(&msg, id->key->rsa->e);
|
||||
buffer_put_bignum(&msg, id->key->rsa->n);
|
||||
} else {
|
||||
unsigned char *blob;
|
||||
unsigned int blen;
|
||||
dsa_make_key_blob(id->key, &blob, &blen);
|
||||
key_to_blob(id->key, &blob, &blen);
|
||||
buffer_put_string(&msg, blob, blen);
|
||||
xfree(blob);
|
||||
}
|
||||
|
@ -178,7 +177,7 @@ process_authentication_challenge1(SocketEntry *e)
|
|||
unsigned int response_type;
|
||||
|
||||
buffer_init(&msg);
|
||||
key = key_new(KEY_RSA);
|
||||
key = key_new(KEY_RSA1);
|
||||
challenge = BN_new();
|
||||
|
||||
buffer_get_int(&e->input); /* ignored */
|
||||
|
@ -251,11 +250,11 @@ process_sign_request2(SocketEntry *e)
|
|||
if (flags & SSH_AGENT_OLD_SIGNATURE)
|
||||
datafellows = SSH_BUG_SIGBLOB;
|
||||
|
||||
key = dsa_key_from_blob(blob, blen);
|
||||
key = key_from_blob(blob, blen);
|
||||
if (key != NULL) {
|
||||
private = lookup_private_key(key, NULL, 2);
|
||||
if (private != NULL)
|
||||
ok = dsa_sign(private, &signature, &slen, data, dlen);
|
||||
ok = key_sign(private, &signature, &slen, data, dlen);
|
||||
}
|
||||
key_free(key);
|
||||
buffer_init(&msg);
|
||||
|
@ -287,7 +286,7 @@ process_remove_identity(SocketEntry *e, int version)
|
|||
|
||||
switch(version){
|
||||
case 1:
|
||||
key = key_new(KEY_RSA);
|
||||
key = key_new(KEY_RSA1);
|
||||
bits = buffer_get_int(&e->input);
|
||||
buffer_get_bignum(&e->input, key->rsa->e);
|
||||
buffer_get_bignum(&e->input, key->rsa->n);
|
||||
|
@ -298,7 +297,7 @@ process_remove_identity(SocketEntry *e, int version)
|
|||
break;
|
||||
case 2:
|
||||
blob = buffer_get_string(&e->input, &blen);
|
||||
key = dsa_key_from_blob(blob, blen);
|
||||
key = key_from_blob(blob, blen);
|
||||
xfree(blob);
|
||||
break;
|
||||
}
|
||||
|
@ -315,8 +314,12 @@ process_remove_identity(SocketEntry *e, int version)
|
|||
Idtab *tab = idtab_lookup(version);
|
||||
key_free(tab->identities[idx].key);
|
||||
xfree(tab->identities[idx].comment);
|
||||
if (idx != tab->nentries)
|
||||
tab->identities[idx] = tab->identities[tab->nentries];
|
||||
if (tab->nentries < 1)
|
||||
fatal("process_remove_identity: "
|
||||
"internal error: tab->nentries %d",
|
||||
tab->nentries);
|
||||
if (idx != tab->nentries - 1)
|
||||
tab->identities[idx] = tab->identities[tab->nentries - 1];
|
||||
tab->nentries--;
|
||||
success = 1;
|
||||
}
|
||||
|
@ -348,80 +351,81 @@ process_remove_all_identities(SocketEntry *e, int version)
|
|||
return;
|
||||
}
|
||||
|
||||
void
|
||||
generate_additional_parameters(RSA *rsa)
|
||||
{
|
||||
BIGNUM *aux;
|
||||
BN_CTX *ctx;
|
||||
/* Generate additional parameters */
|
||||
aux = BN_new();
|
||||
ctx = BN_CTX_new();
|
||||
|
||||
BN_sub(aux, rsa->q, BN_value_one());
|
||||
BN_mod(rsa->dmq1, rsa->d, aux, ctx);
|
||||
|
||||
BN_sub(aux, rsa->p, BN_value_one());
|
||||
BN_mod(rsa->dmp1, rsa->d, aux, ctx);
|
||||
|
||||
BN_clear_free(aux);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
process_add_identity(SocketEntry *e, int version)
|
||||
{
|
||||
Key *k = NULL;
|
||||
RSA *rsa;
|
||||
BIGNUM *aux;
|
||||
BN_CTX *ctx;
|
||||
char *type;
|
||||
char *type_name;
|
||||
char *comment;
|
||||
int success = 0;
|
||||
int type, success = 0;
|
||||
Idtab *tab = idtab_lookup(version);
|
||||
|
||||
switch (version) {
|
||||
case 1:
|
||||
k = key_new(KEY_RSA);
|
||||
rsa = k->rsa;
|
||||
|
||||
/* allocate mem for private key */
|
||||
/* XXX rsa->n and rsa->e are already allocated */
|
||||
rsa->d = BN_new();
|
||||
rsa->iqmp = BN_new();
|
||||
rsa->q = BN_new();
|
||||
rsa->p = BN_new();
|
||||
rsa->dmq1 = BN_new();
|
||||
rsa->dmp1 = BN_new();
|
||||
|
||||
buffer_get_int(&e->input); /* ignored */
|
||||
|
||||
buffer_get_bignum(&e->input, rsa->n);
|
||||
buffer_get_bignum(&e->input, rsa->e);
|
||||
buffer_get_bignum(&e->input, rsa->d);
|
||||
buffer_get_bignum(&e->input, rsa->iqmp);
|
||||
k = key_new_private(KEY_RSA1);
|
||||
buffer_get_int(&e->input); /* ignored */
|
||||
buffer_get_bignum(&e->input, k->rsa->n);
|
||||
buffer_get_bignum(&e->input, k->rsa->e);
|
||||
buffer_get_bignum(&e->input, k->rsa->d);
|
||||
buffer_get_bignum(&e->input, k->rsa->iqmp);
|
||||
|
||||
/* SSH and SSL have p and q swapped */
|
||||
buffer_get_bignum(&e->input, rsa->q); /* p */
|
||||
buffer_get_bignum(&e->input, rsa->p); /* q */
|
||||
buffer_get_bignum(&e->input, k->rsa->q); /* p */
|
||||
buffer_get_bignum(&e->input, k->rsa->p); /* q */
|
||||
|
||||
/* Generate additional parameters */
|
||||
aux = BN_new();
|
||||
ctx = BN_CTX_new();
|
||||
|
||||
BN_sub(aux, rsa->q, BN_value_one());
|
||||
BN_mod(rsa->dmq1, rsa->d, aux, ctx);
|
||||
|
||||
BN_sub(aux, rsa->p, BN_value_one());
|
||||
BN_mod(rsa->dmp1, rsa->d, aux, ctx);
|
||||
|
||||
BN_clear_free(aux);
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
generate_additional_parameters(k->rsa);
|
||||
break;
|
||||
case 2:
|
||||
type = buffer_get_string(&e->input, NULL);
|
||||
if (strcmp(type, KEX_DSS)) {
|
||||
type_name = buffer_get_string(&e->input, NULL);
|
||||
type = key_type_from_name(type_name);
|
||||
xfree(type_name);
|
||||
switch(type) {
|
||||
case KEY_DSA:
|
||||
k = key_new_private(type);
|
||||
buffer_get_bignum2(&e->input, k->dsa->p);
|
||||
buffer_get_bignum2(&e->input, k->dsa->q);
|
||||
buffer_get_bignum2(&e->input, k->dsa->g);
|
||||
buffer_get_bignum2(&e->input, k->dsa->pub_key);
|
||||
buffer_get_bignum2(&e->input, k->dsa->priv_key);
|
||||
break;
|
||||
case KEY_RSA:
|
||||
k = key_new_private(type);
|
||||
buffer_get_bignum2(&e->input, k->rsa->n);
|
||||
buffer_get_bignum2(&e->input, k->rsa->e);
|
||||
buffer_get_bignum2(&e->input, k->rsa->d);
|
||||
buffer_get_bignum2(&e->input, k->rsa->iqmp);
|
||||
buffer_get_bignum2(&e->input, k->rsa->p);
|
||||
buffer_get_bignum2(&e->input, k->rsa->q);
|
||||
|
||||
/* Generate additional parameters */
|
||||
generate_additional_parameters(k->rsa);
|
||||
break;
|
||||
default:
|
||||
buffer_clear(&e->input);
|
||||
xfree(type);
|
||||
goto send;
|
||||
}
|
||||
xfree(type);
|
||||
|
||||
k = key_new(KEY_DSA);
|
||||
|
||||
/* allocate mem for private key */
|
||||
k->dsa->priv_key = BN_new();
|
||||
|
||||
buffer_get_bignum2(&e->input, k->dsa->p);
|
||||
buffer_get_bignum2(&e->input, k->dsa->q);
|
||||
buffer_get_bignum2(&e->input, k->dsa->g);
|
||||
buffer_get_bignum2(&e->input, k->dsa->pub_key);
|
||||
buffer_get_bignum2(&e->input, k->dsa->priv_key);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
comment = buffer_get_string(&e->input, NULL);
|
||||
if (k == NULL) {
|
||||
xfree(comment);
|
||||
|
@ -670,13 +674,6 @@ main(int ac, char **av)
|
|||
|
||||
init_rng();
|
||||
|
||||
/* check if RSA support exists */
|
||||
if (rsa_alive() == 0) {
|
||||
fprintf(stderr,
|
||||
"%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
|
||||
__progname);
|
||||
exit(1);
|
||||
}
|
||||
#ifdef __GNU_LIBRARY__
|
||||
while ((ch = getopt(ac, av, "+cks")) != -1) {
|
||||
#else /* __GNU_LIBRARY__ */
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: dsa.c,v 1.11 2000/09/07 20:27:51 deraadt Exp $");
|
||||
RCSID("$OpenBSD: ssh-dss.c,v 1.1 2000/11/12 19:50:38 markus Exp $");
|
||||
|
||||
#include "ssh.h"
|
||||
#include "xmalloc.h"
|
||||
|
@ -32,88 +32,17 @@ RCSID("$OpenBSD: dsa.c,v 1.11 2000/09/07 20:27:51 deraadt Exp $");
|
|||
#include "compat.h"
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/pem.h>
|
||||
|
||||
#include <openssl/hmac.h>
|
||||
#include "kex.h"
|
||||
#include "key.h"
|
||||
#include "uuencode.h"
|
||||
|
||||
#define INTBLOB_LEN 20
|
||||
#define SIGBLOB_LEN (2*INTBLOB_LEN)
|
||||
|
||||
Key *
|
||||
dsa_key_from_blob(char *blob, int blen)
|
||||
{
|
||||
Buffer b;
|
||||
char *ktype;
|
||||
int rlen;
|
||||
DSA *dsa;
|
||||
Key *key;
|
||||
|
||||
#ifdef DEBUG_DSS
|
||||
dump_base64(stderr, blob, blen);
|
||||
#endif
|
||||
/* fetch & parse DSA/DSS pubkey */
|
||||
buffer_init(&b);
|
||||
buffer_append(&b, blob, blen);
|
||||
ktype = buffer_get_string(&b, NULL);
|
||||
if (strcmp(KEX_DSS, ktype) != 0) {
|
||||
error("dsa_key_from_blob: cannot handle type %s", ktype);
|
||||
buffer_free(&b);
|
||||
xfree(ktype);
|
||||
return NULL;
|
||||
}
|
||||
key = key_new(KEY_DSA);
|
||||
dsa = key->dsa;
|
||||
buffer_get_bignum2(&b, dsa->p);
|
||||
buffer_get_bignum2(&b, dsa->q);
|
||||
buffer_get_bignum2(&b, dsa->g);
|
||||
buffer_get_bignum2(&b, dsa->pub_key);
|
||||
rlen = buffer_len(&b);
|
||||
if(rlen != 0)
|
||||
error("dsa_key_from_blob: remaining bytes in key blob %d", rlen);
|
||||
buffer_free(&b);
|
||||
xfree(ktype);
|
||||
|
||||
#ifdef DEBUG_DSS
|
||||
DSA_print_fp(stderr, dsa, 8);
|
||||
#endif
|
||||
return key;
|
||||
}
|
||||
int
|
||||
dsa_make_key_blob(Key *key, unsigned char **blobp, unsigned int *lenp)
|
||||
{
|
||||
Buffer b;
|
||||
int len;
|
||||
unsigned char *buf;
|
||||
|
||||
if (key == NULL || key->type != KEY_DSA)
|
||||
return 0;
|
||||
buffer_init(&b);
|
||||
buffer_put_cstring(&b, KEX_DSS);
|
||||
buffer_put_bignum2(&b, key->dsa->p);
|
||||
buffer_put_bignum2(&b, key->dsa->q);
|
||||
buffer_put_bignum2(&b, key->dsa->g);
|
||||
buffer_put_bignum2(&b, key->dsa->pub_key);
|
||||
len = buffer_len(&b);
|
||||
buf = xmalloc(len);
|
||||
memcpy(buf, buffer_ptr(&b), len);
|
||||
memset(buffer_ptr(&b), 0, len);
|
||||
buffer_free(&b);
|
||||
if (lenp != NULL)
|
||||
*lenp = len;
|
||||
if (blobp != NULL)
|
||||
*blobp = buf;
|
||||
return len;
|
||||
}
|
||||
int
|
||||
dsa_sign(
|
||||
ssh_dss_sign(
|
||||
Key *key,
|
||||
unsigned char **sigp, int *lenp,
|
||||
unsigned char *data, int datalen)
|
||||
|
@ -130,7 +59,7 @@ dsa_sign(
|
|||
Buffer b;
|
||||
|
||||
if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
|
||||
error("dsa_sign: no DSA key");
|
||||
error("ssh_dss_sign: no DSA key");
|
||||
return -1;
|
||||
}
|
||||
digest = xmalloc(evp_md->md_size);
|
||||
|
@ -140,7 +69,7 @@ dsa_sign(
|
|||
|
||||
sig = DSA_do_sign(digest, evp_md->md_size, key->dsa);
|
||||
if (sig == NULL) {
|
||||
fatal("dsa_sign: cannot sign");
|
||||
fatal("ssh_dss_sign: cannot sign");
|
||||
}
|
||||
|
||||
rlen = BN_num_bytes(sig->r);
|
||||
|
@ -168,7 +97,7 @@ dsa_sign(
|
|||
} else {
|
||||
/* ietf-drafts */
|
||||
buffer_init(&b);
|
||||
buffer_put_cstring(&b, KEX_DSS);
|
||||
buffer_put_cstring(&b, "ssh-dss");
|
||||
buffer_put_string(&b, sigblob, SIGBLOB_LEN);
|
||||
len = buffer_len(&b);
|
||||
ret = xmalloc(len);
|
||||
|
@ -182,7 +111,7 @@ dsa_sign(
|
|||
return 0;
|
||||
}
|
||||
int
|
||||
dsa_verify(
|
||||
ssh_dss_verify(
|
||||
Key *key,
|
||||
unsigned char *signature, int signaturelen,
|
||||
unsigned char *data, int datalen)
|
||||
|
@ -194,12 +123,12 @@ dsa_verify(
|
|||
EVP_MD_CTX md;
|
||||
unsigned char *sigblob;
|
||||
char *txt;
|
||||
unsigned int len;
|
||||
unsigned int len, dlen;
|
||||
int rlen;
|
||||
int ret;
|
||||
|
||||
if (key == NULL || key->type != KEY_DSA || key->dsa == NULL) {
|
||||
error("dsa_verify: no DSA key");
|
||||
error("ssh_dss_verify: no DSA key");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -225,8 +154,8 @@ dsa_verify(
|
|||
buffer_init(&b);
|
||||
buffer_append(&b, (char *) signature, signaturelen);
|
||||
ktype = buffer_get_string(&b, NULL);
|
||||
if (strcmp(KEX_DSS, ktype) != 0) {
|
||||
error("dsa_verify: cannot handle type %s", ktype);
|
||||
if (strcmp("ssh-dss", ktype) != 0) {
|
||||
error("ssh_dss_verify: cannot handle type %s", ktype);
|
||||
buffer_free(&b);
|
||||
return -1;
|
||||
}
|
||||
|
@ -258,14 +187,15 @@ dsa_verify(
|
|||
}
|
||||
|
||||
/* sha1 the data */
|
||||
digest = xmalloc(evp_md->md_size);
|
||||
dlen = evp_md->md_size;
|
||||
digest = xmalloc(dlen);
|
||||
EVP_DigestInit(&md, evp_md);
|
||||
EVP_DigestUpdate(&md, data, datalen);
|
||||
EVP_DigestFinal(&md, digest, NULL);
|
||||
|
||||
ret = DSA_do_verify(digest, evp_md->md_size, sig, key->dsa);
|
||||
ret = DSA_do_verify(digest, dlen, sig, key->dsa);
|
||||
|
||||
memset(digest, 0, evp_md->md_size);
|
||||
memset(digest, 0, dlen);
|
||||
xfree(digest);
|
||||
DSA_SIG_free(sig);
|
||||
|
||||
|
@ -281,24 +211,6 @@ dsa_verify(
|
|||
txt = "error";
|
||||
break;
|
||||
}
|
||||
debug("dsa_verify: signature %s", txt);
|
||||
debug("ssh_dss_verify: signature %s", txt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Key *
|
||||
dsa_generate_key(unsigned int bits)
|
||||
{
|
||||
DSA *dsa = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
|
||||
Key *k;
|
||||
if (dsa == NULL) {
|
||||
fatal("DSA_generate_parameters failed");
|
||||
}
|
||||
if (!DSA_generate_key(dsa)) {
|
||||
fatal("DSA_generate_keys failed");
|
||||
}
|
||||
|
||||
k = key_new(KEY_EMPTY);
|
||||
k->type = KEY_DSA;
|
||||
k->dsa = dsa;
|
||||
return k;
|
||||
}
|
|
@ -24,22 +24,16 @@
|
|||
#ifndef DSA_H
|
||||
#define DSA_H
|
||||
|
||||
Key *dsa_key_from_blob(char *blob, int blen);
|
||||
int dsa_make_key_blob(Key *key, unsigned char **blobp, unsigned int *lenp);
|
||||
|
||||
int
|
||||
dsa_sign(
|
||||
ssh_dss_sign(
|
||||
Key *key,
|
||||
unsigned char **sigp, int *lenp,
|
||||
unsigned char *data, int datalen);
|
||||
|
||||
int
|
||||
dsa_verify(
|
||||
ssh_dss_verify(
|
||||
Key *key,
|
||||
unsigned char *signature, int signaturelen,
|
||||
unsigned char *data, int datalen);
|
||||
|
||||
Key *
|
||||
dsa_generate_key(unsigned int bits);
|
||||
|
||||
#endif
|
24
ssh-keygen.1
24
ssh-keygen.1
|
@ -43,8 +43,9 @@
|
|||
.Nd authentication key generation
|
||||
.Sh SYNOPSIS
|
||||
.Nm ssh-keygen
|
||||
.Op Fl dq
|
||||
.Op Fl q
|
||||
.Op Fl b Ar bits
|
||||
.Op Fl t Ar type
|
||||
.Op Fl N Ar new_passphrase
|
||||
.Op Fl C Ar comment
|
||||
.Op Fl f Ar output_keyfile
|
||||
|
@ -79,8 +80,8 @@ generates and manages authentication keys for
|
|||
.Nm
|
||||
defaults to generating an RSA key for use by protocols 1.3 and 1.5;
|
||||
specifying the
|
||||
.Fl d
|
||||
flag will create a DSA key instead for use by protocol 2.0.
|
||||
.Fl t
|
||||
allows you to create a key for use by protocol 2.0.
|
||||
.Pp
|
||||
Normally each user wishing to use SSH
|
||||
with RSA or DSA authentication runs this once to create the authentication
|
||||
|
@ -154,6 +155,17 @@ Silence
|
|||
Used by
|
||||
.Pa /etc/rc
|
||||
when creating a new key.
|
||||
.It Fl t Ar type
|
||||
Specifies the type of the key to create.
|
||||
The possible values are
|
||||
.Dq rsa1
|
||||
for protocol version 1 and
|
||||
.Dq rsa
|
||||
or
|
||||
.Dq dsa
|
||||
for protocol version 2.
|
||||
The default is
|
||||
.Dq rsa .
|
||||
.It Fl C Ar comment
|
||||
Provides the new comment.
|
||||
.It Fl N Ar new_passphrase
|
||||
|
@ -173,7 +185,7 @@ SSH2-compatible private (or public) key file and
|
|||
print an OpenSSH compatible private (or public) key to stdout.
|
||||
.It Fl y
|
||||
This option will read a private
|
||||
OpenSSH DSA format file and print an OpenSSH DSA public key to stdout.
|
||||
OpenSSH format file and print an OpenSSH public key to stdout.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width Ds
|
||||
|
@ -211,10 +223,10 @@ Contains the public key for authentication.
|
|||
The contents of this file should be added to
|
||||
.Pa $HOME/.ssh/authorized_keys2
|
||||
on all machines
|
||||
where you wish to log in using DSA authentication.
|
||||
where you wish to log in using public key authentication.
|
||||
There is no need to keep the contents of this file secret.
|
||||
.El
|
||||
.Sh AUTHOR
|
||||
.Sh AUTHORS
|
||||
Tatu Ylonen <ylo@cs.hut.fi>
|
||||
.Pp
|
||||
OpenSSH
|
||||
|
|
115
ssh-keygen.c
115
ssh-keygen.c
|
@ -12,7 +12,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: ssh-keygen.c,v 1.32 2000/10/09 21:30:44 markus Exp $");
|
||||
RCSID("$OpenBSD: ssh-keygen.c,v 1.33 2000/11/12 19:50:38 markus Exp $");
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
|
@ -23,7 +23,6 @@ RCSID("$OpenBSD: ssh-keygen.c,v 1.32 2000/10/09 21:30:44 markus Exp $");
|
|||
#include "xmalloc.h"
|
||||
#include "key.h"
|
||||
#include "rsa.h"
|
||||
#include "dsa.h"
|
||||
#include "authfile.h"
|
||||
#include "uuencode.h"
|
||||
|
||||
|
@ -67,7 +66,10 @@ char *identity_comment = NULL;
|
|||
int convert_to_ssh2 = 0;
|
||||
int convert_from_ssh2 = 0;
|
||||
int print_public = 0;
|
||||
int dsa_mode = 0;
|
||||
|
||||
/* key type */
|
||||
int dsa_mode = 0; /* compat */
|
||||
char *key_type_name = NULL;
|
||||
|
||||
/* argv0 */
|
||||
#ifdef HAVE___PROGNAME
|
||||
|
@ -130,12 +132,12 @@ do_convert_to_ssh2(struct passwd *pw)
|
|||
perror(identity_file);
|
||||
exit(1);
|
||||
}
|
||||
k = key_new(KEY_DSA);
|
||||
k = key_new(KEY_UNSPEC);
|
||||
if (!try_load_key(identity_file, k)) {
|
||||
fprintf(stderr, "load failed\n");
|
||||
exit(1);
|
||||
}
|
||||
dsa_make_key_blob(k, &blob, &len);
|
||||
key_to_blob(k, &blob, &len);
|
||||
fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
|
||||
fprintf(stdout,
|
||||
"Comment: \"%d-bit %s, converted from OpenSSH by %s@%s\"\n",
|
||||
|
@ -266,7 +268,7 @@ do_convert_from_ssh2(struct passwd *pw)
|
|||
}
|
||||
k = private ?
|
||||
do_convert_private_ssh2_from_blob(blob, blen) :
|
||||
dsa_key_from_blob(blob, blen);
|
||||
key_from_blob(blob, blen);
|
||||
if (k == NULL) {
|
||||
fprintf(stderr, "decode blob failed.\n");
|
||||
exit(1);
|
||||
|
@ -288,8 +290,6 @@ void
|
|||
do_print_public(struct passwd *pw)
|
||||
{
|
||||
Key *k;
|
||||
int len;
|
||||
unsigned char *blob;
|
||||
struct stat st;
|
||||
|
||||
if (!have_identity)
|
||||
|
@ -298,16 +298,14 @@ do_print_public(struct passwd *pw)
|
|||
perror(identity_file);
|
||||
exit(1);
|
||||
}
|
||||
k = key_new(KEY_DSA);
|
||||
k = key_new(KEY_UNSPEC);
|
||||
if (!try_load_key(identity_file, k)) {
|
||||
fprintf(stderr, "load failed\n");
|
||||
exit(1);
|
||||
}
|
||||
dsa_make_key_blob(k, &blob, &len);
|
||||
if (!key_write(k, stdout))
|
||||
fprintf(stderr, "key_write failed");
|
||||
key_free(k);
|
||||
xfree(blob);
|
||||
fprintf(stdout, "\n");
|
||||
exit(0);
|
||||
}
|
||||
|
@ -315,12 +313,11 @@ do_print_public(struct passwd *pw)
|
|||
void
|
||||
do_fingerprint(struct passwd *pw)
|
||||
{
|
||||
/* XXX RSA1 only */
|
||||
|
||||
FILE *f;
|
||||
Key *public;
|
||||
char *comment = NULL, *cp, *ep, line[16*1024];
|
||||
int i, skip = 0, num = 1, invalid = 1;
|
||||
int i, skip = 0, num = 1, invalid = 1, success = 0;
|
||||
unsigned int ignore;
|
||||
struct stat st;
|
||||
|
||||
|
@ -330,14 +327,27 @@ do_fingerprint(struct passwd *pw)
|
|||
perror(identity_file);
|
||||
exit(1);
|
||||
}
|
||||
public = key_new(KEY_RSA);
|
||||
public = key_new(KEY_RSA1);
|
||||
if (load_public_key(identity_file, public, &comment)) {
|
||||
printf("%d %s %s\n", BN_num_bits(public->rsa->n),
|
||||
key_fingerprint(public), comment);
|
||||
success = 1;
|
||||
} else {
|
||||
key_free(public);
|
||||
public = key_new(KEY_UNSPEC);
|
||||
if (try_load_public_key(identity_file, public, &comment))
|
||||
success = 1;
|
||||
else
|
||||
error("try_load_public_key KEY_UNSPEC failed");
|
||||
}
|
||||
if (success) {
|
||||
printf("%d %s %s\n", key_size(public), key_fingerprint(public), comment);
|
||||
key_free(public);
|
||||
xfree(comment);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* XXX RSA1 only */
|
||||
|
||||
public = key_new(KEY_RSA1);
|
||||
f = fopen(identity_file, "r");
|
||||
if (f != NULL) {
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
|
@ -404,7 +414,7 @@ do_change_passphrase(struct passwd *pw)
|
|||
struct stat st;
|
||||
Key *private;
|
||||
Key *public;
|
||||
int type = dsa_mode ? KEY_DSA : KEY_RSA;
|
||||
int type = KEY_RSA1;
|
||||
|
||||
if (!have_identity)
|
||||
ask_filename(pw, "Enter file in which the key is");
|
||||
|
@ -412,18 +422,13 @@ do_change_passphrase(struct passwd *pw)
|
|||
perror(identity_file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (type == KEY_RSA) {
|
||||
/* XXX this works currently only for RSA */
|
||||
public = key_new(type);
|
||||
if (!load_public_key(identity_file, public, NULL)) {
|
||||
printf("%s is not a valid key file.\n", identity_file);
|
||||
exit(1);
|
||||
}
|
||||
public = key_new(type);
|
||||
if (!load_public_key(identity_file, public, NULL)) {
|
||||
type = KEY_UNSPEC;
|
||||
} else {
|
||||
/* Clear the public key since we are just about to load the whole file. */
|
||||
key_free(public);
|
||||
}
|
||||
|
||||
/* Try to load the file with empty passphrase. */
|
||||
private = key_new(type);
|
||||
if (!load_private_key(identity_file, "", private, &comment)) {
|
||||
|
@ -508,13 +513,13 @@ do_change_comment(struct passwd *pw)
|
|||
* Try to load the public key from the file the verify that it is
|
||||
* readable and of the proper format.
|
||||
*/
|
||||
public = key_new(KEY_RSA);
|
||||
public = key_new(KEY_RSA1);
|
||||
if (!load_public_key(identity_file, public, NULL)) {
|
||||
printf("%s is not a valid key file.\n", identity_file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
private = key_new(KEY_RSA);
|
||||
private = key_new(KEY_RSA1);
|
||||
if (load_private_key(identity_file, "", private, &comment))
|
||||
passphrase = xstrdup("");
|
||||
else {
|
||||
|
@ -583,7 +588,7 @@ do_change_comment(struct passwd *pw)
|
|||
void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage: %s [-lpqxXydc] [-b bits] [-f file] [-C comment] [-N new-pass] [-P pass]\n", __progname);
|
||||
printf("Usage: %s [-lpqxXyc] [-t type] [-b bits] [-f file] [-C comment] [-N new-pass] [-P pass]\n", __progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -598,8 +603,10 @@ main(int ac, char **av)
|
|||
int opt;
|
||||
struct stat st;
|
||||
FILE *f;
|
||||
int type = KEY_RSA1;
|
||||
Key *private;
|
||||
Key *public;
|
||||
|
||||
extern int optind;
|
||||
extern char *optarg;
|
||||
|
||||
|
@ -618,7 +625,7 @@ main(int ac, char **av)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
while ((opt = getopt(ac, av, "dqpclRxXyb:f:P:N:C:")) != EOF) {
|
||||
while ((opt = getopt(ac, av, "dqpclRxXyb:f:t:P:N:C:")) != EOF) {
|
||||
switch (opt) {
|
||||
case 'b':
|
||||
bits = atoi(optarg);
|
||||
|
@ -662,10 +669,8 @@ main(int ac, char **av)
|
|||
break;
|
||||
|
||||
case 'R':
|
||||
if (rsa_alive() == 0)
|
||||
exit(1);
|
||||
else
|
||||
exit(0);
|
||||
/* unused */
|
||||
exit(0);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
|
@ -681,9 +686,15 @@ main(int ac, char **av)
|
|||
break;
|
||||
|
||||
case 'd':
|
||||
key_type_name = "dsa";
|
||||
dsa_mode = 1;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
key_type_name = optarg;
|
||||
dsa_mode = (strcmp(optarg, "dsa") == 0);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
|
@ -697,13 +708,6 @@ main(int ac, char **av)
|
|||
printf("Can only have one of -p and -c.\n");
|
||||
usage();
|
||||
}
|
||||
/* check if RSA support is needed and exists */
|
||||
if (dsa_mode == 0 && rsa_alive() == 0) {
|
||||
fprintf(stderr,
|
||||
"%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
|
||||
__progname);
|
||||
exit(1);
|
||||
}
|
||||
if (print_fingerprint)
|
||||
do_fingerprint(pw);
|
||||
if (change_passphrase)
|
||||
|
@ -719,22 +723,21 @@ main(int ac, char **av)
|
|||
|
||||
arc4random_stir();
|
||||
|
||||
if (dsa_mode != 0) {
|
||||
if (!quiet)
|
||||
printf("Generating DSA parameter and key.\n");
|
||||
public = private = dsa_generate_key(bits);
|
||||
if (private == NULL) {
|
||||
fprintf(stderr, "dsa_generate_keys failed");
|
||||
if (key_type_name != NULL) {
|
||||
type = key_type_from_name(key_type_name);
|
||||
if (type == KEY_UNSPEC) {
|
||||
fprintf(stderr, "unknown key type %s", key_type_name);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
if (quiet)
|
||||
rsa_set_verbose(0);
|
||||
/* Generate the rsa key pair. */
|
||||
public = key_new(KEY_RSA);
|
||||
private = key_new(KEY_RSA);
|
||||
rsa_generate_key(private->rsa, public->rsa, bits);
|
||||
}
|
||||
if (!quiet)
|
||||
printf("Generating public/private key pair.\n");
|
||||
private = key_generate(type, bits);
|
||||
if (private == NULL) {
|
||||
fprintf(stderr, "key_generate failed");
|
||||
exit(1);
|
||||
}
|
||||
public = key_from_private(private);
|
||||
|
||||
if (!have_identity)
|
||||
ask_filename(pw, "Enter file in which to save the key");
|
||||
|
@ -803,9 +806,7 @@ passphrase_again:
|
|||
xfree(passphrase1);
|
||||
|
||||
/* Clear the private key and the random number generator. */
|
||||
if (private != public) {
|
||||
key_free(private);
|
||||
}
|
||||
key_free(private);
|
||||
arc4random_stir();
|
||||
|
||||
if (!quiet)
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
53
ssh.1
|
@ -34,7 +34,7 @@
|
|||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $OpenBSD: ssh.1,v 1.64 2000/10/16 21:46:31 markus Exp $
|
||||
.\" $OpenBSD: ssh.1,v 1.68 2000/11/12 19:50:38 markus Exp $
|
||||
.Dd September 25, 1999
|
||||
.Dt SSH 1
|
||||
.Os
|
||||
|
@ -209,9 +209,9 @@ At first, the client attempts to authenticate using the public key method.
|
|||
If this method fails password authentication is tried.
|
||||
.Pp
|
||||
The public key method is similar to RSA authentication described
|
||||
in the previous section except that the DSA algorithm is used
|
||||
instead of the patented RSA algorithm.
|
||||
The client uses his private DSA key
|
||||
in the previous section except that the DSA or RSA algorithm is used
|
||||
instead.
|
||||
The client uses his private key
|
||||
.Pa $HOME/.ssh/id_dsa
|
||||
to sign the session identifier and sends the result to the server.
|
||||
The server checks whether the matching public key is listed in
|
||||
|
@ -331,7 +331,7 @@ identifications for all hosts it has ever been used with.
|
|||
RSA host keys are stored in
|
||||
.Pa $HOME/.ssh/known_hosts
|
||||
and
|
||||
DSA host keys are stored in
|
||||
host keys used in the protocol version 2 are stored in
|
||||
.Pa $HOME/.ssh/known_hosts2
|
||||
in the user's home directory.
|
||||
Additionally, the files
|
||||
|
@ -352,7 +352,8 @@ The
|
|||
.Cm StrictHostKeyChecking
|
||||
option (see below) can be used to prevent logins to machines whose
|
||||
host key is not known or has changed.
|
||||
.Sh OPTIONS
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a
|
||||
Disables forwarding of the authentication agent connection.
|
||||
|
@ -407,7 +408,7 @@ something like
|
|||
Allows remote hosts to connect to local forwarded ports.
|
||||
.It Fl i Ar identity_file
|
||||
Selects the file from which the identity (private key) for
|
||||
RSA authentication is read.
|
||||
RSA or DSA authentication is read.
|
||||
Default is
|
||||
.Pa $HOME/.ssh/identity
|
||||
in the user's home directory.
|
||||
|
@ -552,6 +553,22 @@ Forces
|
|||
.Nm
|
||||
to use IPv6 addresses only.
|
||||
.El
|
||||
.Pp
|
||||
If
|
||||
.Nm
|
||||
is not invoked with one of the standard program names
|
||||
.Pf ( Dq ssh ,
|
||||
.Dq slogin ,
|
||||
.Dq rsh ,
|
||||
.Dq rlogin ,
|
||||
or
|
||||
.Dq remsh ) ,
|
||||
it uses this name as its
|
||||
.Ar hostname
|
||||
argument.
|
||||
This is consistent with traditional
|
||||
.Xr rsh 1
|
||||
behavior.
|
||||
.Sh CONFIGURATION FILES
|
||||
.Nm
|
||||
obtains configuration data from the following sources (in this order):
|
||||
|
@ -660,14 +677,12 @@ Specifies the number of tries (one per second) to make before falling
|
|||
back to rsh or exiting.
|
||||
The argument must be an integer.
|
||||
This may be useful in scripts if the connection sometimes fails.
|
||||
.It Cm DSAAuthentication
|
||||
Specifies whether to try DSA authentication.
|
||||
.It Cm PubkeyAuthentication
|
||||
Specifies whether to try public key authentication.
|
||||
The argument to this keyword must be
|
||||
.Dq yes
|
||||
or
|
||||
.Dq no .
|
||||
DSA authentication will only be
|
||||
attempted if a DSA identity file exists.
|
||||
Note that this option applies to protocol version 2 only.
|
||||
.It Cm EscapeChar
|
||||
Sets the escape character (default:
|
||||
|
@ -745,16 +760,6 @@ syntax to refer to a user's home directory.
|
|||
It is possible to have
|
||||
multiple identity files specified in configuration files; all these
|
||||
identities will be tried in sequence.
|
||||
.It Cm IdentityFile2
|
||||
Specifies the file from which the user's DSA authentication identity
|
||||
is read (default
|
||||
.Pa $HOME/.ssh/id_dsa
|
||||
in the user's home directory).
|
||||
The file name may use the tilde
|
||||
syntax to refer to a user's home directory.
|
||||
It is possible to have
|
||||
multiple identity files specified in configuration files; all these
|
||||
identities will be tried in sequence.
|
||||
.It Cm KeepAlive
|
||||
Specifies whether the system should send keepalive messages to the
|
||||
other side.
|
||||
|
@ -1096,7 +1101,7 @@ spaces).
|
|||
This file is not highly sensitive, but the recommended
|
||||
permissions are read/write for the user, and not accessible by others.
|
||||
.It Pa $HOME/.ssh/authorized_keys2
|
||||
Lists the DSA keys that can be used for logging in as this user.
|
||||
Lists the public keys (DSA/RSA) that can be used for logging in as this user.
|
||||
This file is not highly sensitive, but the recommended
|
||||
permissions are read/write for the user, and not accessible by others.
|
||||
.It Pa /etc/ssh_known_hosts, /etc/ssh_known_hosts2
|
||||
|
@ -1104,7 +1109,7 @@ Systemwide list of known host keys.
|
|||
.Pa /etc/ssh_known_hosts
|
||||
contains RSA and
|
||||
.Pa /etc/ssh_known_hosts2
|
||||
contains DSA keys.
|
||||
contains DSA or RSA keys for protocol version 2.
|
||||
These files should be prepared by the
|
||||
system administrator to contain the public host keys of all machines in the
|
||||
organization.
|
||||
|
@ -1219,7 +1224,7 @@ above.
|
|||
A version of this library which includes support for the RSA algorithm
|
||||
is required for proper operation.
|
||||
.El
|
||||
.Sh AUTHOR
|
||||
.Sh AUTHORS
|
||||
OpenSSH
|
||||
is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen,
|
||||
but with bugs removed and newer features re-added.
|
||||
|
|
193
ssh.c
193
ssh.c
|
@ -39,11 +39,12 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: ssh.c,v 1.69 2000/10/27 07:32:19 markus Exp $");
|
||||
RCSID("$OpenBSD: ssh.c,v 1.72 2000/11/12 19:50:38 markus Exp $");
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "ssh.h"
|
||||
|
@ -218,8 +219,9 @@ rsh_connect(char *host, char *user, Buffer * command)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
int ssh_session(void);
|
||||
int ssh_session2(void);
|
||||
int ssh_session(void);
|
||||
int ssh_session2(void);
|
||||
int guess_identity_file_type(const char *filename);
|
||||
|
||||
/*
|
||||
* Main program for the ssh client.
|
||||
|
@ -370,14 +372,13 @@ main(int ac, char **av)
|
|||
case 'i':
|
||||
if (stat(optarg, &st) < 0) {
|
||||
fprintf(stderr, "Warning: Identity file %s does not exist.\n",
|
||||
optarg);
|
||||
optarg);
|
||||
break;
|
||||
}
|
||||
if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES)
|
||||
fatal("Too many identity files specified (max %d)",
|
||||
SSH_MAX_IDENTITY_FILES);
|
||||
options.identity_files[options.num_identity_files++] =
|
||||
xstrdup(optarg);
|
||||
SSH_MAX_IDENTITY_FILES);
|
||||
options.identity_files[options.num_identity_files++] = xstrdup(optarg);
|
||||
break;
|
||||
case 't':
|
||||
tty_flag = 1;
|
||||
|
@ -487,6 +488,7 @@ main(int ac, char **av)
|
|||
usage();
|
||||
|
||||
SSLeay_add_all_algorithms();
|
||||
ERR_load_crypto_strings();
|
||||
|
||||
/* Initialize the command to execute on remote host. */
|
||||
buffer_init(&command);
|
||||
|
@ -563,20 +565,6 @@ main(int ac, char **av)
|
|||
/* reinit */
|
||||
log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
|
||||
|
||||
/* check if RSA support exists */
|
||||
if ((options.protocol & SSH_PROTO_1) &&
|
||||
rsa_alive() == 0) {
|
||||
log("%s: no RSA support in libssl and libcrypto. See ssl(8).",
|
||||
__progname);
|
||||
log("Disabling protocol version 1");
|
||||
options.protocol &= ~ (SSH_PROTO_1|SSH_PROTO_1_PREFERRED);
|
||||
}
|
||||
if (! options.protocol & (SSH_PROTO_1|SSH_PROTO_2)) {
|
||||
fprintf(stderr, "%s: No protocol version available.\n",
|
||||
__progname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (options.user == NULL)
|
||||
options.user = xstrdup(pw->pw_name);
|
||||
|
||||
|
@ -589,6 +577,8 @@ main(int ac, char **av)
|
|||
if (!options.use_privileged_port) {
|
||||
#else
|
||||
if (original_effective_uid != 0 || !options.use_privileged_port) {
|
||||
debug("Rhosts Authentication methods disabled, "
|
||||
"originating port will not be trusted.");
|
||||
#endif
|
||||
options.rhosts_authentication = 0;
|
||||
options.rhosts_rsa_authentication = 0;
|
||||
|
@ -635,7 +625,7 @@ main(int ac, char **av)
|
|||
if (ok && (options.protocol & SSH_PROTO_1)) {
|
||||
Key k;
|
||||
host_private_key = RSA_new();
|
||||
k.type = KEY_RSA;
|
||||
k.type = KEY_RSA1;
|
||||
k.rsa = host_private_key;
|
||||
if (load_private_key(HOST_KEY_FILE, "", &k, NULL))
|
||||
host_private_key_loaded = 1;
|
||||
|
@ -682,23 +672,23 @@ main(int ac, char **av)
|
|||
}
|
||||
exit(1);
|
||||
}
|
||||
/* Expand ~ in options.identity_files. */
|
||||
/* Expand ~ in options.identity_files, known host file names. */
|
||||
/* XXX mem-leaks */
|
||||
for (i = 0; i < options.num_identity_files; i++)
|
||||
for (i = 0; i < options.num_identity_files; i++) {
|
||||
options.identity_files[i] =
|
||||
tilde_expand_filename(options.identity_files[i], original_real_uid);
|
||||
for (i = 0; i < options.num_identity_files2; i++)
|
||||
options.identity_files2[i] =
|
||||
tilde_expand_filename(options.identity_files2[i], original_real_uid);
|
||||
/* Expand ~ in known host file names. */
|
||||
options.system_hostfile = tilde_expand_filename(options.system_hostfile,
|
||||
original_real_uid);
|
||||
options.user_hostfile = tilde_expand_filename(options.user_hostfile,
|
||||
original_real_uid);
|
||||
options.system_hostfile2 = tilde_expand_filename(options.system_hostfile2,
|
||||
original_real_uid);
|
||||
options.user_hostfile2 = tilde_expand_filename(options.user_hostfile2,
|
||||
original_real_uid);
|
||||
tilde_expand_filename(options.identity_files[i], original_real_uid);
|
||||
options.identity_files_type[i] = guess_identity_file_type(options.identity_files[i]);
|
||||
debug("identity file %s type %d", options.identity_files[i],
|
||||
options.identity_files_type[i]);
|
||||
}
|
||||
options.system_hostfile =
|
||||
tilde_expand_filename(options.system_hostfile, original_real_uid);
|
||||
options.user_hostfile =
|
||||
tilde_expand_filename(options.user_hostfile, original_real_uid);
|
||||
options.system_hostfile2 =
|
||||
tilde_expand_filename(options.system_hostfile2, original_real_uid);
|
||||
options.user_hostfile2 =
|
||||
tilde_expand_filename(options.user_hostfile2, original_real_uid);
|
||||
|
||||
/* Log into the remote system. This never returns if the login fails. */
|
||||
ssh_login(host_private_key_loaded, host_private_key,
|
||||
|
@ -752,16 +742,57 @@ x11_get_proto(char *proto, int proto_len, char *data, int data_len)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ssh_init_forwarding(void)
|
||||
{
|
||||
int i;
|
||||
/* Initiate local TCP/IP port forwardings. */
|
||||
for (i = 0; i < options.num_local_forwards; i++) {
|
||||
debug("Connections to local port %d forwarded to remote address %.200s:%d",
|
||||
options.local_forwards[i].port,
|
||||
options.local_forwards[i].host,
|
||||
options.local_forwards[i].host_port);
|
||||
channel_request_local_forwarding(
|
||||
options.local_forwards[i].port,
|
||||
options.local_forwards[i].host,
|
||||
options.local_forwards[i].host_port,
|
||||
options.gateway_ports);
|
||||
}
|
||||
|
||||
/* Initiate remote TCP/IP port forwardings. */
|
||||
for (i = 0; i < options.num_remote_forwards; i++) {
|
||||
debug("Connections to remote port %d forwarded to local address %.200s:%d",
|
||||
options.remote_forwards[i].port,
|
||||
options.remote_forwards[i].host,
|
||||
options.remote_forwards[i].host_port);
|
||||
channel_request_remote_forwarding(
|
||||
options.remote_forwards[i].port,
|
||||
options.remote_forwards[i].host,
|
||||
options.remote_forwards[i].host_port);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
check_agent_present(void)
|
||||
{
|
||||
if (options.forward_agent) {
|
||||
/* Clear agent forwarding if we don\'t have an agent. */
|
||||
int authfd = ssh_get_authentication_socket();
|
||||
if (authfd < 0)
|
||||
options.forward_agent = 0;
|
||||
else
|
||||
ssh_close_authentication_socket(authfd);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ssh_session(void)
|
||||
{
|
||||
int type;
|
||||
int i;
|
||||
int plen;
|
||||
int interactive = 0;
|
||||
int have_tty = 0;
|
||||
struct winsize ws;
|
||||
int authfd;
|
||||
char *cp;
|
||||
|
||||
/* Enable compression if requested. */
|
||||
|
@ -845,14 +876,10 @@ ssh_session(void)
|
|||
/* Tell the packet module whether this is an interactive session. */
|
||||
packet_set_interactive(interactive, options.keepalives);
|
||||
|
||||
/* Clear agent forwarding if we don\'t have an agent. */
|
||||
authfd = ssh_get_authentication_socket();
|
||||
if (authfd < 0)
|
||||
options.forward_agent = 0;
|
||||
else
|
||||
ssh_close_authentication_socket(authfd);
|
||||
|
||||
/* Request authentication agent forwarding if appropriate. */
|
||||
check_agent_present();
|
||||
|
||||
if (options.forward_agent) {
|
||||
debug("Requesting authentication agent forwarding.");
|
||||
auth_request_forwarding();
|
||||
|
@ -863,28 +890,9 @@ ssh_session(void)
|
|||
if (type != SSH_SMSG_SUCCESS)
|
||||
log("Warning: Remote host denied authentication agent forwarding.");
|
||||
}
|
||||
/* Initiate local TCP/IP port forwardings. */
|
||||
for (i = 0; i < options.num_local_forwards; i++) {
|
||||
debug("Connections to local port %d forwarded to remote address %.200s:%d",
|
||||
options.local_forwards[i].port,
|
||||
options.local_forwards[i].host,
|
||||
options.local_forwards[i].host_port);
|
||||
channel_request_local_forwarding(options.local_forwards[i].port,
|
||||
options.local_forwards[i].host,
|
||||
options.local_forwards[i].host_port,
|
||||
options.gateway_ports);
|
||||
}
|
||||
|
||||
/* Initiate remote TCP/IP port forwardings. */
|
||||
for (i = 0; i < options.num_remote_forwards; i++) {
|
||||
debug("Connections to remote port %d forwarded to local address %.200s:%d",
|
||||
options.remote_forwards[i].port,
|
||||
options.remote_forwards[i].host,
|
||||
options.remote_forwards[i].host_port);
|
||||
channel_request_remote_forwarding(options.remote_forwards[i].port,
|
||||
options.remote_forwards[i].host,
|
||||
options.remote_forwards[i].host_port);
|
||||
}
|
||||
/* Initiate port forwardings. */
|
||||
ssh_init_forwarding();
|
||||
|
||||
/* If requested, let ssh continue in the background. */
|
||||
if (fork_after_authentication_flag)
|
||||
|
@ -915,27 +923,10 @@ ssh_session(void)
|
|||
return client_loop(have_tty, tty_flag ? options.escape_char : -1, 0);
|
||||
}
|
||||
|
||||
void
|
||||
init_local_fwd(void)
|
||||
{
|
||||
int i;
|
||||
/* Initiate local TCP/IP port forwardings. */
|
||||
for (i = 0; i < options.num_local_forwards; i++) {
|
||||
debug("Connections to local port %d forwarded to remote address %.200s:%d",
|
||||
options.local_forwards[i].port,
|
||||
options.local_forwards[i].host,
|
||||
options.local_forwards[i].host_port);
|
||||
channel_request_local_forwarding(options.local_forwards[i].port,
|
||||
options.local_forwards[i].host,
|
||||
options.local_forwards[i].host_port,
|
||||
options.gateway_ports);
|
||||
}
|
||||
}
|
||||
|
||||
extern void client_set_session_ident(int id);
|
||||
|
||||
void
|
||||
client_init(int id, void *arg)
|
||||
ssh_session2_callback(int id, void *arg)
|
||||
{
|
||||
int len;
|
||||
debug("client_init id %d arg %d", id, (int)arg);
|
||||
|
@ -974,6 +965,13 @@ client_init(int id, void *arg)
|
|||
/* XXX wait for reply */
|
||||
}
|
||||
|
||||
check_agent_present();
|
||||
if (options.forward_agent) {
|
||||
debug("Requesting authentication agent forwarding.");
|
||||
channel_request_start(id, "auth-agent-req@openssh.com", 0);
|
||||
packet_send();
|
||||
}
|
||||
|
||||
len = buffer_len(&command);
|
||||
if (len > 0) {
|
||||
if (len > 900)
|
||||
|
@ -1016,8 +1014,8 @@ ssh_session2(void)
|
|||
if (!isatty(err))
|
||||
set_nonblock(err);
|
||||
|
||||
/* should be pre-session */
|
||||
init_local_fwd();
|
||||
/* XXX should be pre-session */
|
||||
ssh_init_forwarding();
|
||||
|
||||
/* If requested, let ssh continue in the background. */
|
||||
if (fork_after_authentication_flag)
|
||||
|
@ -1036,7 +1034,28 @@ ssh_session2(void)
|
|||
xstrdup("client-session"), /*nonblock*/0);
|
||||
|
||||
channel_open(id);
|
||||
channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0);
|
||||
channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION,
|
||||
ssh_session2_callback, (void *)0);
|
||||
|
||||
return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id);
|
||||
}
|
||||
|
||||
int
|
||||
guess_identity_file_type(const char *filename)
|
||||
{
|
||||
struct stat st;
|
||||
Key *public;
|
||||
int type = KEY_RSA1; /* default */
|
||||
|
||||
if (stat(filename, &st) < 0) {
|
||||
perror(filename);
|
||||
return KEY_UNSPEC;
|
||||
}
|
||||
public = key_new(type);
|
||||
if (!load_public_key(filename, public, NULL)) {
|
||||
/* ok, so we will assume this is 'some' key */
|
||||
type = KEY_UNSPEC;
|
||||
}
|
||||
key_free(public);
|
||||
return type;
|
||||
}
|
||||
|
|
13
ssh_config
13
ssh_config
|
@ -13,9 +13,9 @@
|
|||
# Site-wide defaults for various options
|
||||
|
||||
# Host *
|
||||
# ForwardAgent yes
|
||||
# ForwardX11 yes
|
||||
# RhostsAuthentication yes
|
||||
# ForwardAgent no
|
||||
# ForwardX11 no
|
||||
# RhostsAuthentication no
|
||||
# RhostsRSAAuthentication yes
|
||||
# RSAAuthentication yes
|
||||
# PasswordAuthentication yes
|
||||
|
@ -23,9 +23,12 @@
|
|||
# UseRsh no
|
||||
# BatchMode no
|
||||
# CheckHostIP yes
|
||||
# StrictHostKeyChecking no
|
||||
# StrictHostKeyChecking yes
|
||||
# IdentityFile ~/.ssh/identity
|
||||
# IdentityFile ~/.ssh/id_dsa
|
||||
# IdentityFile ~/.ssh/id_rsa1
|
||||
# IdentityFile ~/.ssh/id_rsa2
|
||||
# Port 22
|
||||
# Protocol 2,1
|
||||
# Protocol 1,2
|
||||
# Cipher blowfish
|
||||
# EscapeChar ~
|
||||
|
|
12
sshconnect.c
12
sshconnect.c
|
@ -13,7 +13,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sshconnect.c,v 1.79 2000/09/17 15:52:51 markus Exp $");
|
||||
RCSID("$OpenBSD: sshconnect.c,v 1.81 2000/11/06 23:16:35 markus Exp $");
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dsa.h>
|
||||
|
@ -249,9 +249,9 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
|
|||
/* Create a socket for connecting. */
|
||||
sock = ssh_create_socket(original_real_uid,
|
||||
#ifdef HAVE_CYGWIN
|
||||
!anonymous && port < IPPORT_RESERVED,
|
||||
!anonymous,
|
||||
#else
|
||||
!anonymous && geteuid() == 0 && port < IPPORT_RESERVED,
|
||||
!anonymous && geteuid() == 0,
|
||||
#endif
|
||||
ai->ai_family);
|
||||
if (sock < 0)
|
||||
|
@ -321,6 +321,7 @@ ssh_exchange_identification()
|
|||
int remote_major, remote_minor, i, mismatch;
|
||||
int connection_in = packet_get_connection_in();
|
||||
int connection_out = packet_get_connection_out();
|
||||
int minor1 = PROTOCOL_MINOR_1;
|
||||
|
||||
/* Read other side\'s version identification. */
|
||||
for (;;) {
|
||||
|
@ -374,9 +375,10 @@ ssh_exchange_identification()
|
|||
}
|
||||
if (remote_minor < 3) {
|
||||
fatal("Remote machine has too old SSH software version.");
|
||||
} else if (remote_minor == 3) {
|
||||
} else if (remote_minor == 3 || remote_minor == 4) {
|
||||
/* We speak 1.3, too. */
|
||||
enable_compat13();
|
||||
minor1 = 3;
|
||||
if (options.forward_agent) {
|
||||
log("Agent forwarding disabled for protocol 1.3");
|
||||
options.forward_agent = 0;
|
||||
|
@ -402,7 +404,7 @@ ssh_exchange_identification()
|
|||
/* Send our own protocol version identification. */
|
||||
snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
|
||||
compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
|
||||
compat20 ? PROTOCOL_MINOR_2 : PROTOCOL_MINOR_1,
|
||||
compat20 ? PROTOCOL_MINOR_2 : minor1,
|
||||
SSH_VERSION);
|
||||
if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf))
|
||||
fatal("write: %.100s", strerror(errno));
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sshconnect1.c,v 1.8 2000/10/12 09:59:19 markus Exp $");
|
||||
RCSID("$OpenBSD: sshconnect1.c,v 1.9 2000/11/12 19:50:38 markus Exp $");
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dsa.h>
|
||||
|
@ -62,7 +62,7 @@ try_agent_authentication()
|
|||
return 0;
|
||||
|
||||
challenge = BN_new();
|
||||
key = key_new(KEY_RSA);
|
||||
key = key_new(KEY_RSA1);
|
||||
|
||||
/* Loop through identities served by the agent. */
|
||||
for (key = ssh_get_first_identity(auth, &comment, 1);
|
||||
|
@ -196,7 +196,7 @@ try_rsa_authentication(const char *authfile)
|
|||
int plen, clen;
|
||||
|
||||
/* Try to load identification for the authentication key. */
|
||||
public = key_new(KEY_RSA);
|
||||
public = key_new(KEY_RSA1);
|
||||
if (!load_public_key(authfile, public, &comment)) {
|
||||
key_free(public);
|
||||
/* Could not load it. Fail. */
|
||||
|
@ -237,7 +237,7 @@ try_rsa_authentication(const char *authfile)
|
|||
|
||||
debug("Received RSA challenge from server.");
|
||||
|
||||
private = key_new(KEY_RSA);
|
||||
private = key_new(KEY_RSA1);
|
||||
/*
|
||||
* Load the private key. Try first with empty passphrase; if it
|
||||
* fails, ask for a passphrase.
|
||||
|
@ -760,7 +760,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
|
|||
packet_integrity_check(payload_len,
|
||||
8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4,
|
||||
SSH_SMSG_PUBLIC_KEY);
|
||||
k.type = KEY_RSA;
|
||||
k.type = KEY_RSA1;
|
||||
k.rsa = host_key;
|
||||
check_host_key(host, hostaddr, &k,
|
||||
options.user_hostfile, options.system_hostfile);
|
||||
|
@ -994,7 +994,8 @@ ssh_userauth(
|
|||
|
||||
/* Try RSA authentication for each identity. */
|
||||
for (i = 0; i < options.num_identity_files; i++)
|
||||
if (try_rsa_authentication(options.identity_files[i]))
|
||||
if (options.identity_files_type[i] == KEY_RSA1 &&
|
||||
try_rsa_authentication(options.identity_files[i]))
|
||||
return;
|
||||
}
|
||||
/* Try skey authentication if the server supports it. */
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sshconnect2.c,v 1.27 2000/10/19 16:45:16 provos Exp $");
|
||||
RCSID("$OpenBSD: sshconnect2.c,v 1.28 2000/11/12 19:50:38 markus Exp $");
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
@ -45,7 +45,6 @@ RCSID("$OpenBSD: sshconnect2.c,v 1.27 2000/10/19 16:45:16 provos Exp $");
|
|||
#include "kex.h"
|
||||
#include "myproposal.h"
|
||||
#include "key.h"
|
||||
#include "dsa.h"
|
||||
#include "sshconnect.h"
|
||||
#include "authfile.h"
|
||||
#include "cli.h"
|
||||
|
@ -196,7 +195,7 @@ ssh_dh1_client(Kex *kex, char *host, struct sockaddr *hostaddr,
|
|||
|
||||
/* key, cert */
|
||||
server_host_key_blob = packet_get_string(&sbloblen);
|
||||
server_host_key = dsa_key_from_blob(server_host_key_blob, sbloblen);
|
||||
server_host_key = key_from_blob(server_host_key_blob, sbloblen);
|
||||
if (server_host_key == NULL)
|
||||
fatal("cannot decode server_host_key_blob");
|
||||
|
||||
|
@ -258,8 +257,8 @@ ssh_dh1_client(Kex *kex, char *host, struct sockaddr *hostaddr,
|
|||
fprintf(stderr, "%02x", (hash[i])&0xff);
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
if (dsa_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1)
|
||||
fatal("dsa_verify failed for server_host_key");
|
||||
if (key_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1)
|
||||
fatal("key_verify failed for server_host_key");
|
||||
key_free(server_host_key);
|
||||
|
||||
kex_derive_keys(kex, hash, shared_secret);
|
||||
|
@ -366,7 +365,7 @@ ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr,
|
|||
|
||||
/* key, cert */
|
||||
server_host_key_blob = packet_get_string(&sbloblen);
|
||||
server_host_key = dsa_key_from_blob(server_host_key_blob, sbloblen);
|
||||
server_host_key = key_from_blob(server_host_key_blob, sbloblen);
|
||||
if (server_host_key == NULL)
|
||||
fatal("cannot decode server_host_key_blob");
|
||||
|
||||
|
@ -429,8 +428,8 @@ ssh_dhgex_client(Kex *kex, char *host, struct sockaddr *hostaddr,
|
|||
fprintf(stderr, "%02x", (hash[i])&0xff);
|
||||
fprintf(stderr, "\n");
|
||||
#endif
|
||||
if (dsa_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1)
|
||||
fatal("dsa_verify failed for server_host_key");
|
||||
if (key_verify(server_host_key, (unsigned char *)signature, slen, hash, 20) != 1)
|
||||
fatal("key_verify failed for server_host_key");
|
||||
key_free(server_host_key);
|
||||
|
||||
kex_derive_keys(kex, hash, shared_secret);
|
||||
|
@ -485,7 +484,7 @@ Authmethod *authmethod_lookup(const char *name);
|
|||
Authmethod authmethods[] = {
|
||||
{"publickey",
|
||||
userauth_pubkey,
|
||||
&options.dsa_authentication,
|
||||
&options.pubkey_authentication,
|
||||
NULL},
|
||||
{"password",
|
||||
userauth_passwd,
|
||||
|
@ -653,8 +652,10 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
|
|||
int ret = -1;
|
||||
int have_sig = 1;
|
||||
|
||||
dsa_make_key_blob(k, &blob, &bloblen);
|
||||
|
||||
if (key_to_blob(k, &blob, &bloblen) == 0) {
|
||||
/* we cannot handle this key */
|
||||
return 0;
|
||||
}
|
||||
/* data to be signed */
|
||||
buffer_init(&b);
|
||||
if (datafellows & SSH_OLD_SESSIONID) {
|
||||
|
@ -672,7 +673,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
|
|||
authctxt->service);
|
||||
buffer_put_cstring(&b, authctxt->method->name);
|
||||
buffer_put_char(&b, have_sig);
|
||||
buffer_put_cstring(&b, KEX_DSS);
|
||||
buffer_put_cstring(&b, key_ssh_name(k));
|
||||
buffer_put_string(&b, blob, bloblen);
|
||||
|
||||
/* generate signature */
|
||||
|
@ -682,7 +683,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
|
|||
buffer_free(&b);
|
||||
return 0;
|
||||
}
|
||||
#ifdef DEBUG_DSS
|
||||
#ifdef DEBUG_PK
|
||||
buffer_dump(&b);
|
||||
#endif
|
||||
if (datafellows & SSH_BUG_PUBKEYAUTH) {
|
||||
|
@ -693,7 +694,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
|
|||
buffer_put_cstring(&b, authctxt->service);
|
||||
buffer_put_cstring(&b, authctxt->method->name);
|
||||
buffer_put_char(&b, have_sig);
|
||||
buffer_put_cstring(&b, KEX_DSS);
|
||||
buffer_put_cstring(&b, key_ssh_name(k));
|
||||
buffer_put_string(&b, blob, bloblen);
|
||||
}
|
||||
xfree(blob);
|
||||
|
@ -719,10 +720,10 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
|
|||
}
|
||||
|
||||
/* sign callback */
|
||||
int dsa_sign_cb(Authctxt *authctxt, Key *key, unsigned char **sigp, int *lenp,
|
||||
int key_sign_cb(Authctxt *authctxt, Key *key, unsigned char **sigp, int *lenp,
|
||||
unsigned char *data, int datalen)
|
||||
{
|
||||
return dsa_sign(key, sigp, lenp, data, datalen);
|
||||
return key_sign(key, sigp, lenp, data, datalen);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -738,14 +739,13 @@ userauth_pubkey_identity(Authctxt *authctxt, char *filename)
|
|||
}
|
||||
debug("try pubkey: %s", filename);
|
||||
|
||||
k = key_new(KEY_DSA);
|
||||
k = key_new(KEY_UNSPEC);
|
||||
if (!load_private_key(filename, "", k, NULL)) {
|
||||
int success = 0;
|
||||
char *passphrase;
|
||||
char prompt[300];
|
||||
snprintf(prompt, sizeof prompt,
|
||||
"Enter passphrase for %s key '%.100s': ",
|
||||
key_type(k), filename);
|
||||
"Enter passphrase for key '%.100s': ", filename);
|
||||
for (i = 0; i < options.number_of_password_prompts; i++) {
|
||||
passphrase = read_passphrase(prompt, 0);
|
||||
if (strcmp(passphrase, "") != 0) {
|
||||
|
@ -766,7 +766,7 @@ userauth_pubkey_identity(Authctxt *authctxt, char *filename)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
ret = sign_and_send_pubkey(authctxt, k, dsa_sign_cb);
|
||||
ret = sign_and_send_pubkey(authctxt, k, key_sign_cb);
|
||||
key_free(k);
|
||||
return ret;
|
||||
}
|
||||
|
@ -782,24 +782,26 @@ int
|
|||
userauth_pubkey_agent(Authctxt *authctxt)
|
||||
{
|
||||
static int called = 0;
|
||||
int ret = 0;
|
||||
char *comment;
|
||||
Key *k;
|
||||
int ret;
|
||||
|
||||
if (called == 0) {
|
||||
k = ssh_get_first_identity(authctxt->agent, &comment, 2);
|
||||
if (ssh_get_num_identities(authctxt->agent, 2) == 0)
|
||||
debug2("userauth_pubkey_agent: no keys at all");
|
||||
called = 1;
|
||||
} else {
|
||||
k = ssh_get_next_identity(authctxt->agent, &comment, 2);
|
||||
}
|
||||
k = ssh_get_next_identity(authctxt->agent, &comment, 2);
|
||||
if (k == NULL) {
|
||||
debug2("no more DSA keys from agent");
|
||||
return 0;
|
||||
debug2("userauth_pubkey_agent: no more keys");
|
||||
} else {
|
||||
debug("userauth_pubkey_agent: trying agent key %s", comment);
|
||||
xfree(comment);
|
||||
ret = sign_and_send_pubkey(authctxt, k, agent_sign_cb);
|
||||
key_free(k);
|
||||
}
|
||||
debug("trying DSA agent key %s", comment);
|
||||
xfree(comment);
|
||||
ret = sign_and_send_pubkey(authctxt, k, agent_sign_cb);
|
||||
key_free(k);
|
||||
if (ret == 0)
|
||||
debug2("userauth_pubkey_agent: no message sent");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -809,10 +811,17 @@ userauth_pubkey(Authctxt *authctxt)
|
|||
static int idx = 0;
|
||||
int sent = 0;
|
||||
|
||||
if (authctxt->agent != NULL)
|
||||
sent = userauth_pubkey_agent(authctxt);
|
||||
while (sent == 0 && idx < options.num_identity_files2)
|
||||
sent = userauth_pubkey_identity(authctxt, options.identity_files2[idx++]);
|
||||
if (authctxt->agent != NULL) {
|
||||
do {
|
||||
sent = userauth_pubkey_agent(authctxt);
|
||||
} while(!sent && authctxt->agent->howmany > 0);
|
||||
}
|
||||
while (!sent && idx < options.num_identity_files) {
|
||||
if (options.identity_files_type[idx] != KEY_RSA1)
|
||||
sent = userauth_pubkey_identity(authctxt,
|
||||
options.identity_files[idx]);
|
||||
idx++;
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
|
||||
|
|
30
sshd.8
30
sshd.8
|
@ -34,7 +34,7 @@
|
|||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $OpenBSD: sshd.8,v 1.70 2000/10/16 09:38:44 djm Exp $
|
||||
.\" $OpenBSD: sshd.8,v 1.72 2000/11/12 19:50:38 markus Exp $
|
||||
.Dd September 25, 1999
|
||||
.Dt SSHD 8
|
||||
.Os
|
||||
|
@ -144,7 +144,7 @@ through a cryptographic message authentication code
|
|||
(hmac-sha1 or hmac-md5).
|
||||
.Pp
|
||||
Protocol version 2 provides a public key based
|
||||
user authentication method (DSAAuthentication)
|
||||
user authentication method (PubkeyAuthentication)
|
||||
and conventional password authentication.
|
||||
.Pp
|
||||
.Ss Command execution and data forwarding
|
||||
|
@ -359,8 +359,8 @@ and
|
|||
can be used as wildcards in the patterns.
|
||||
Only user names are valid; a numerical user ID isn't recognized.
|
||||
By default login is allowed regardless of the user name.
|
||||
.It Cm DSAAuthentication
|
||||
Specifies whether DSA authentication is allowed.
|
||||
.It Cm PubkeyAuthentication
|
||||
Specifies whether public key authentication is allowed.
|
||||
The default is
|
||||
.Dq yes .
|
||||
Note that this option applies to protocol version 2 only.
|
||||
|
@ -373,20 +373,20 @@ or
|
|||
.Dq no .
|
||||
The default is
|
||||
.Dq no .
|
||||
.It Cm HostDSAKey
|
||||
Specifies the file containing the private DSA host key (default
|
||||
.Pa /etc/ssh_host_dsa_key )
|
||||
used by SSH protocol 2.0.
|
||||
Note that
|
||||
.Nm
|
||||
disables protocol 2.0 if this file is group/world-accessible.
|
||||
.It Cm HostKey
|
||||
Specifies the file containing the private RSA host key (default
|
||||
Specifies the file containing the private host keys (default
|
||||
.Pa /etc/ssh_host_key )
|
||||
used by SSH protocols 1.3 and 1.5.
|
||||
used by SSH protocol versions 1 and 2.
|
||||
Note that
|
||||
.Nm
|
||||
disables protocols 1.3 and 1.5 if this file is group/world-accessible.
|
||||
if this file is group/world-accessible.
|
||||
It is possible to have multiple host key files.
|
||||
.Dq rsa1
|
||||
keys are used for version 1 and
|
||||
.Dq dsa
|
||||
or
|
||||
.Dq rsa
|
||||
are used for version 2 of the SSH protocol.
|
||||
.It Cm IgnoreRhosts
|
||||
Specifies that
|
||||
.Pa .rhosts
|
||||
|
@ -1039,7 +1039,7 @@ This can be used to specify
|
|||
machine-specific login-time initializations globally.
|
||||
This file should be writable only by root, and should be world-readable.
|
||||
.El
|
||||
.Sh AUTHOR
|
||||
.Sh AUTHORS
|
||||
OpenSSH
|
||||
is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen,
|
||||
but with bugs removed and newer features re-added.
|
||||
|
|
318
sshd.c
318
sshd.c
|
@ -40,7 +40,7 @@
|
|||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sshd.c,v 1.132 2000/10/13 18:34:46 markus Exp $");
|
||||
RCSID("$OpenBSD: sshd.c,v 1.134 2000/11/12 19:50:38 markus Exp $");
|
||||
|
||||
#include "xmalloc.h"
|
||||
#include "rsa.h"
|
||||
|
@ -61,7 +61,6 @@ RCSID("$OpenBSD: sshd.c,v 1.132 2000/10/13 18:34:46 markus Exp $");
|
|||
#include <openssl/dsa.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include "key.h"
|
||||
#include "dsa.h"
|
||||
#include "dh.h"
|
||||
|
||||
#include "auth.h"
|
||||
|
@ -140,9 +139,11 @@ char *server_version_string = NULL;
|
|||
* not very useful. Currently, memory locking is not implemented.
|
||||
*/
|
||||
struct {
|
||||
RSA *private_key; /* Private part of empheral server key. */
|
||||
RSA *host_key; /* Private part of host key. */
|
||||
Key *dsa_host_key; /* Private DSA host key. */
|
||||
Key *server_key; /* empheral server key */
|
||||
Key *ssh1_host_key; /* ssh1 host key */
|
||||
Key **host_keys; /* all private host keys */
|
||||
int have_ssh1_key;
|
||||
int have_ssh2_key;
|
||||
} sensitive_data;
|
||||
|
||||
/*
|
||||
|
@ -154,10 +155,6 @@ int key_used = 0;
|
|||
/* This is set to true when SIGHUP is received. */
|
||||
int received_sighup = 0;
|
||||
|
||||
/* Public side of the server key. This value is regenerated regularly with
|
||||
the private key. */
|
||||
RSA *public_key;
|
||||
|
||||
/* session identifier, used by RSA-auth */
|
||||
unsigned char session_id[16];
|
||||
|
||||
|
@ -266,6 +263,17 @@ grace_alarm_handler(int sig)
|
|||
*/
|
||||
/* XXX do we really want this work to be done in a signal handler ? -m */
|
||||
void
|
||||
generate_empheral_server_key(void)
|
||||
{
|
||||
log("Generating %s%d bit RSA key.", sensitive_data.server_key ? "new " : "",
|
||||
options.server_key_bits);
|
||||
if (sensitive_data.server_key != NULL)
|
||||
key_free(sensitive_data.server_key);
|
||||
sensitive_data.server_key = key_generate(KEY_RSA1, options.server_key_bits);
|
||||
arc4random_stir();
|
||||
log("RSA key generation complete.");
|
||||
}
|
||||
void
|
||||
key_regeneration_alarm(int sig)
|
||||
{
|
||||
int save_errno = errno;
|
||||
|
@ -273,21 +281,8 @@ key_regeneration_alarm(int sig)
|
|||
/* Check if we should generate a new key. */
|
||||
if (key_used) {
|
||||
/* This should really be done in the background. */
|
||||
log("Generating new %d bit RSA key.", options.server_key_bits);
|
||||
|
||||
if (sensitive_data.private_key != NULL)
|
||||
RSA_free(sensitive_data.private_key);
|
||||
sensitive_data.private_key = RSA_new();
|
||||
|
||||
if (public_key != NULL)
|
||||
RSA_free(public_key);
|
||||
public_key = RSA_new();
|
||||
|
||||
rsa_generate_key(sensitive_data.private_key, public_key,
|
||||
options.server_key_bits);
|
||||
arc4random_stir();
|
||||
generate_empheral_server_key();
|
||||
key_used = 0;
|
||||
log("RSA key generation complete.");
|
||||
}
|
||||
/* Reschedule the alarm. */
|
||||
signal(SIGALRM, key_regeneration_alarm);
|
||||
|
@ -422,18 +417,93 @@ sshd_exchange_identification(int sock_in, int sock_out)
|
|||
}
|
||||
|
||||
|
||||
/* Destroy the host and server keys. They will no longer be needed. */
|
||||
void
|
||||
destroy_sensitive_data(void)
|
||||
{
|
||||
/* Destroy the private and public keys. They will no longer be needed. */
|
||||
if (public_key)
|
||||
RSA_free(public_key);
|
||||
if (sensitive_data.private_key)
|
||||
RSA_free(sensitive_data.private_key);
|
||||
if (sensitive_data.host_key)
|
||||
RSA_free(sensitive_data.host_key);
|
||||
if (sensitive_data.dsa_host_key != NULL)
|
||||
key_free(sensitive_data.dsa_host_key);
|
||||
int i;
|
||||
|
||||
if (sensitive_data.server_key) {
|
||||
key_free(sensitive_data.server_key);
|
||||
sensitive_data.server_key = NULL;
|
||||
}
|
||||
for(i = 0; i < options.num_host_key_files; i++) {
|
||||
if (sensitive_data.host_keys[i]) {
|
||||
key_free(sensitive_data.host_keys[i]);
|
||||
sensitive_data.host_keys[i] = NULL;
|
||||
}
|
||||
}
|
||||
sensitive_data.ssh1_host_key = NULL;
|
||||
}
|
||||
Key *
|
||||
load_private_key_autodetect(const char *filename)
|
||||
{
|
||||
struct stat st;
|
||||
int type;
|
||||
Key *public, *private;
|
||||
|
||||
if (stat(filename, &st) < 0) {
|
||||
perror(filename);
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* try to load the public key. right now this only works for RSA1,
|
||||
* since SSH2 keys are fully encrypted
|
||||
*/
|
||||
type = KEY_RSA1;
|
||||
public = key_new(type);
|
||||
if (!load_public_key(filename, public, NULL)) {
|
||||
/* ok, so we will assume this is 'some' key */
|
||||
type = KEY_UNSPEC;
|
||||
}
|
||||
key_free(public);
|
||||
|
||||
/* Ok, try key with empty passphrase */
|
||||
private = key_new(type);
|
||||
if (load_private_key(filename, "", private, NULL)) {
|
||||
debug("load_private_key_autodetect: type %d %s",
|
||||
private->type, key_type(private));
|
||||
return private;
|
||||
}
|
||||
key_free(private);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
list_hostkey_types(void)
|
||||
{
|
||||
static char buf[1024];
|
||||
int i;
|
||||
buf[0] = '\0';
|
||||
for(i = 0; i < options.num_host_key_files; i++) {
|
||||
Key *key = sensitive_data.host_keys[i];
|
||||
if (key == NULL)
|
||||
continue;
|
||||
switch(key->type) {
|
||||
case KEY_RSA:
|
||||
case KEY_DSA:
|
||||
strlcat(buf, key_ssh_name(key), sizeof buf);
|
||||
strlcat(buf, ",", sizeof buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
i = strlen(buf);
|
||||
if (i > 0 && buf[i-1] == ',')
|
||||
buf[i-1] = '\0';
|
||||
debug("list_hostkey_types: %s", buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
Key *
|
||||
get_hostkey_by_type(int type)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < options.num_host_key_files; i++) {
|
||||
Key *key = sensitive_data.host_keys[i];
|
||||
if (key != NULL && key->type == type)
|
||||
return key;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -555,7 +625,11 @@ main(int ac, char **av)
|
|||
options.key_regeneration_time = atoi(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
options.host_key_file = optarg;
|
||||
if (options.num_host_key_files >= MAX_HOSTKEYS) {
|
||||
fprintf(stderr, "too many host keys.\n");
|
||||
exit(1);
|
||||
}
|
||||
options.host_key_files[options.num_host_key_files++] = optarg;
|
||||
break;
|
||||
case 'V':
|
||||
client_version_string = optarg;
|
||||
|
@ -610,39 +684,39 @@ main(int ac, char **av)
|
|||
|
||||
debug("sshd version %.100s", SSH_VERSION);
|
||||
|
||||
sensitive_data.dsa_host_key = NULL;
|
||||
sensitive_data.host_key = NULL;
|
||||
/* load private host keys */
|
||||
sensitive_data.host_keys = xmalloc(options.num_host_key_files*sizeof(Key*));
|
||||
sensitive_data.server_key = NULL;
|
||||
sensitive_data.ssh1_host_key = NULL;
|
||||
sensitive_data.have_ssh1_key = 0;
|
||||
sensitive_data.have_ssh2_key = 0;
|
||||
|
||||
/* check if RSA support exists */
|
||||
if ((options.protocol & SSH_PROTO_1) &&
|
||||
rsa_alive() == 0) {
|
||||
log("no RSA support in libssl and libcrypto. See ssl(8)");
|
||||
log("Disabling protocol version 1");
|
||||
for(i = 0; i < options.num_host_key_files; i++) {
|
||||
Key *key = load_private_key_autodetect(options.host_key_files[i]);
|
||||
if (key == NULL) {
|
||||
error("Could not load host key: %.200s: %.100s",
|
||||
options.host_key_files[i], strerror(errno));
|
||||
continue;
|
||||
}
|
||||
switch(key->type){
|
||||
case KEY_RSA1:
|
||||
sensitive_data.ssh1_host_key = key;
|
||||
sensitive_data.have_ssh1_key = 1;
|
||||
break;
|
||||
case KEY_RSA:
|
||||
case KEY_DSA:
|
||||
sensitive_data.have_ssh2_key = 1;
|
||||
break;
|
||||
}
|
||||
sensitive_data.host_keys[i] = key;
|
||||
}
|
||||
if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) {
|
||||
log("Disabling protocol version 1. Could not load host key");
|
||||
options.protocol &= ~SSH_PROTO_1;
|
||||
}
|
||||
/* Load the RSA/DSA host key. It must have empty passphrase. */
|
||||
if (options.protocol & SSH_PROTO_1) {
|
||||
Key k;
|
||||
sensitive_data.host_key = RSA_new();
|
||||
k.type = KEY_RSA;
|
||||
k.rsa = sensitive_data.host_key;
|
||||
errno = 0;
|
||||
if (!load_private_key(options.host_key_file, "", &k, NULL)) {
|
||||
error("Could not load host key: %.200s: %.100s",
|
||||
options.host_key_file, strerror(errno));
|
||||
log("Disabling protocol version 1");
|
||||
options.protocol &= ~SSH_PROTO_1;
|
||||
}
|
||||
k.rsa = NULL;
|
||||
}
|
||||
if (options.protocol & SSH_PROTO_2) {
|
||||
sensitive_data.dsa_host_key = key_new(KEY_DSA);
|
||||
if (!load_private_key(options.host_dsa_key_file, "", sensitive_data.dsa_host_key, NULL)) {
|
||||
|
||||
error("Could not load DSA host key: %.200s", options.host_dsa_key_file);
|
||||
log("Disabling protocol version 2");
|
||||
options.protocol &= ~SSH_PROTO_2;
|
||||
}
|
||||
if ((options.protocol & SSH_PROTO_2) && !sensitive_data.have_ssh2_key) {
|
||||
log("Disabling protocol version 2. Could not load host key");
|
||||
options.protocol &= ~SSH_PROTO_2;
|
||||
}
|
||||
if (! options.protocol & (SSH_PROTO_1|SSH_PROTO_2)) {
|
||||
if (silent == 0)
|
||||
|
@ -664,11 +738,11 @@ main(int ac, char **av)
|
|||
* hate software patents. I dont know if this can go? Niels
|
||||
*/
|
||||
if (options.server_key_bits >
|
||||
BN_num_bits(sensitive_data.host_key->n) - SSH_KEY_BITS_RESERVED &&
|
||||
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) - SSH_KEY_BITS_RESERVED &&
|
||||
options.server_key_bits <
|
||||
BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED) {
|
||||
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
|
||||
options.server_key_bits =
|
||||
BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED;
|
||||
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED;
|
||||
debug("Forcing server key to %d bits to make it differ from host key.",
|
||||
options.server_key_bits);
|
||||
}
|
||||
|
@ -707,9 +781,6 @@ main(int ac, char **av)
|
|||
/* Reinitialize the log (because of the fork above). */
|
||||
log_init(av0, options.log_level, options.log_facility, log_stderr);
|
||||
|
||||
/* Do not display messages to stdout in RSA code. */
|
||||
rsa_set_verbose(0);
|
||||
|
||||
/* Initialize the random number generator. */
|
||||
arc4random_stir();
|
||||
|
||||
|
@ -731,16 +802,8 @@ main(int ac, char **av)
|
|||
* ttyfd happens to be one of those.
|
||||
*/
|
||||
debug("inetd sockets after dupping: %d, %d", sock_in, sock_out);
|
||||
|
||||
if (options.protocol & SSH_PROTO_1) {
|
||||
public_key = RSA_new();
|
||||
sensitive_data.private_key = RSA_new();
|
||||
log("Generating %d bit RSA key.", options.server_key_bits);
|
||||
rsa_generate_key(sensitive_data.private_key, public_key,
|
||||
options.server_key_bits);
|
||||
arc4random_stir();
|
||||
log("RSA key generation complete.");
|
||||
}
|
||||
if (options.protocol & SSH_PROTO_1)
|
||||
generate_empheral_server_key();
|
||||
} else {
|
||||
for (ai = options.listen_addrs; ai; ai = ai->ai_next) {
|
||||
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
|
||||
|
@ -818,14 +881,7 @@ main(int ac, char **av)
|
|||
}
|
||||
}
|
||||
if (options.protocol & SSH_PROTO_1) {
|
||||
public_key = RSA_new();
|
||||
sensitive_data.private_key = RSA_new();
|
||||
|
||||
log("Generating %d bit RSA key.", options.server_key_bits);
|
||||
rsa_generate_key(sensitive_data.private_key, public_key,
|
||||
options.server_key_bits);
|
||||
arc4random_stir();
|
||||
log("RSA key generation complete.");
|
||||
generate_empheral_server_key();
|
||||
|
||||
/* Schedule server key regeneration alarm. */
|
||||
signal(SIGALRM, key_regeneration_alarm);
|
||||
|
@ -1065,6 +1121,8 @@ main(int ac, char **av)
|
|||
*/
|
||||
if (remote_port >= IPPORT_RESERVED ||
|
||||
remote_port < IPPORT_RESERVED / 2) {
|
||||
debug("Rhosts Authentication methods disabled, "
|
||||
"originating port not trusted.");
|
||||
options.rhosts_authentication = 0;
|
||||
options.rhosts_rsa_authentication = 0;
|
||||
}
|
||||
|
@ -1145,14 +1203,14 @@ do_ssh1_kex()
|
|||
packet_put_char(cookie[i]);
|
||||
|
||||
/* Store our public server RSA key. */
|
||||
packet_put_int(BN_num_bits(public_key->n));
|
||||
packet_put_bignum(public_key->e);
|
||||
packet_put_bignum(public_key->n);
|
||||
packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n));
|
||||
packet_put_bignum(sensitive_data.server_key->rsa->e);
|
||||
packet_put_bignum(sensitive_data.server_key->rsa->n);
|
||||
|
||||
/* Store our public host RSA key. */
|
||||
packet_put_int(BN_num_bits(sensitive_data.host_key->n));
|
||||
packet_put_bignum(sensitive_data.host_key->e);
|
||||
packet_put_bignum(sensitive_data.host_key->n);
|
||||
packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
|
||||
packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e);
|
||||
packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n);
|
||||
|
||||
/* Put protocol flags. */
|
||||
packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
|
||||
|
@ -1190,8 +1248,9 @@ do_ssh1_kex()
|
|||
packet_send();
|
||||
packet_write_wait();
|
||||
|
||||
debug("Sent %d bit public key and %d bit host key.",
|
||||
BN_num_bits(public_key->n), BN_num_bits(sensitive_data.host_key->n));
|
||||
debug("Sent %d bit server key and %d bit host key.",
|
||||
BN_num_bits(sensitive_data.server_key->rsa->n),
|
||||
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));
|
||||
|
||||
/* Read clients reply (cipher type and session key). */
|
||||
packet_read_expect(&plen, SSH_CMSG_SESSION_KEY);
|
||||
|
@ -1223,39 +1282,39 @@ do_ssh1_kex()
|
|||
* Decrypt it using our private server key and private host key (key
|
||||
* with larger modulus first).
|
||||
*/
|
||||
if (BN_cmp(sensitive_data.private_key->n, sensitive_data.host_key->n) > 0) {
|
||||
if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) {
|
||||
/* Private key has bigger modulus. */
|
||||
if (BN_num_bits(sensitive_data.private_key->n) <
|
||||
BN_num_bits(sensitive_data.host_key->n) + SSH_KEY_BITS_RESERVED) {
|
||||
fatal("do_connection: %s: private_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
|
||||
get_remote_ipaddr(),
|
||||
BN_num_bits(sensitive_data.private_key->n),
|
||||
BN_num_bits(sensitive_data.host_key->n),
|
||||
SSH_KEY_BITS_RESERVED);
|
||||
if (BN_num_bits(sensitive_data.server_key->rsa->n) <
|
||||
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
|
||||
fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
|
||||
get_remote_ipaddr(),
|
||||
BN_num_bits(sensitive_data.server_key->rsa->n),
|
||||
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
|
||||
SSH_KEY_BITS_RESERVED);
|
||||
}
|
||||
rsa_private_decrypt(session_key_int, session_key_int,
|
||||
sensitive_data.private_key);
|
||||
sensitive_data.server_key->rsa);
|
||||
rsa_private_decrypt(session_key_int, session_key_int,
|
||||
sensitive_data.host_key);
|
||||
sensitive_data.ssh1_host_key->rsa);
|
||||
} else {
|
||||
/* Host key has bigger modulus (or they are equal). */
|
||||
if (BN_num_bits(sensitive_data.host_key->n) <
|
||||
BN_num_bits(sensitive_data.private_key->n) + SSH_KEY_BITS_RESERVED) {
|
||||
fatal("do_connection: %s: host_key %d < private_key %d + SSH_KEY_BITS_RESERVED %d",
|
||||
get_remote_ipaddr(),
|
||||
BN_num_bits(sensitive_data.host_key->n),
|
||||
BN_num_bits(sensitive_data.private_key->n),
|
||||
SSH_KEY_BITS_RESERVED);
|
||||
if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
|
||||
BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) {
|
||||
fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",
|
||||
get_remote_ipaddr(),
|
||||
BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
|
||||
BN_num_bits(sensitive_data.server_key->rsa->n),
|
||||
SSH_KEY_BITS_RESERVED);
|
||||
}
|
||||
rsa_private_decrypt(session_key_int, session_key_int,
|
||||
sensitive_data.host_key);
|
||||
sensitive_data.ssh1_host_key->rsa);
|
||||
rsa_private_decrypt(session_key_int, session_key_int,
|
||||
sensitive_data.private_key);
|
||||
sensitive_data.server_key->rsa);
|
||||
}
|
||||
|
||||
compute_session_id(session_id, cookie,
|
||||
sensitive_data.host_key->n,
|
||||
sensitive_data.private_key->n);
|
||||
sensitive_data.ssh1_host_key->rsa->n,
|
||||
sensitive_data.server_key->rsa->n);
|
||||
|
||||
/* Destroy the private and public keys. They will no longer be needed. */
|
||||
destroy_sensitive_data();
|
||||
|
@ -1269,8 +1328,8 @@ do_ssh1_kex()
|
|||
len = BN_num_bytes(session_key_int);
|
||||
if (len < 0 || len > sizeof(session_key))
|
||||
fatal("do_connection: bad len from %s: session_key_int %d > sizeof(session_key) %d",
|
||||
get_remote_ipaddr(),
|
||||
len, (int) sizeof(session_key));
|
||||
get_remote_ipaddr(),
|
||||
len, sizeof(session_key));
|
||||
memset(session_key, 0, sizeof(session_key));
|
||||
BN_bn2bin(session_key_int, session_key + sizeof(session_key) - len);
|
||||
|
||||
|
@ -1314,6 +1373,8 @@ do_ssh2_kex()
|
|||
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
|
||||
myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
|
||||
}
|
||||
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = list_hostkey_types();
|
||||
|
||||
server_kexinit = kex_init(myproposal);
|
||||
client_kexinit = xmalloc(sizeof(*client_kexinit));
|
||||
buffer_init(client_kexinit);
|
||||
|
@ -1379,6 +1440,11 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
|
|||
BIGNUM *shared_secret = 0;
|
||||
DH *dh;
|
||||
BIGNUM *dh_client_pub = 0;
|
||||
Key *hostkey;
|
||||
|
||||
hostkey = get_hostkey_by_type(kex->hostkey_type);
|
||||
if (hostkey == NULL)
|
||||
fatal("Unsupported hostkey type %d", kex->hostkey_type);
|
||||
|
||||
/* KEXDH */
|
||||
debug("Wait SSH2_MSG_KEXDH_INIT.");
|
||||
|
@ -1431,8 +1497,7 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
|
|||
xfree(kbuf);
|
||||
|
||||
/* XXX precompute? */
|
||||
dsa_make_key_blob(sensitive_data.dsa_host_key,
|
||||
&server_host_key_blob, &sbloblen);
|
||||
key_to_blob(hostkey, &server_host_key_blob, &sbloblen);
|
||||
|
||||
/* calc H */ /* XXX depends on 'kex' */
|
||||
hash = kex_hash(
|
||||
|
@ -1463,7 +1528,7 @@ ssh_dh1_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
|
|||
|
||||
/* sign H */
|
||||
/* XXX hashlen depends on KEX */
|
||||
dsa_sign(sensitive_data.dsa_host_key, &signature, &slen, hash, 20);
|
||||
key_sign(hostkey, &signature, &slen, hash, 20);
|
||||
|
||||
destroy_sensitive_data();
|
||||
|
||||
|
@ -1503,6 +1568,11 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
|
|||
BIGNUM *shared_secret = 0;
|
||||
DH *dh;
|
||||
BIGNUM *dh_client_pub = 0;
|
||||
Key *hostkey;
|
||||
|
||||
hostkey = get_hostkey_by_type(kex->hostkey_type);
|
||||
if (hostkey == NULL)
|
||||
fatal("Unsupported hostkey type %d", kex->hostkey_type);
|
||||
|
||||
/* KEXDHGEX */
|
||||
debug("Wait SSH2_MSG_KEX_DH_GEX_REQUEST.");
|
||||
|
@ -1564,8 +1634,7 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
|
|||
xfree(kbuf);
|
||||
|
||||
/* XXX precompute? */
|
||||
dsa_make_key_blob(sensitive_data.dsa_host_key,
|
||||
&server_host_key_blob, &sbloblen);
|
||||
key_to_blob(hostkey, &server_host_key_blob, &sbloblen);
|
||||
|
||||
/* calc H */ /* XXX depends on 'kex' */
|
||||
hash = kex_hash_gex(
|
||||
|
@ -1597,7 +1666,7 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
|
|||
|
||||
/* sign H */
|
||||
/* XXX hashlen depends on KEX */
|
||||
dsa_sign(sensitive_data.dsa_host_key, &signature, &slen, hash, 20);
|
||||
key_sign(hostkey, &signature, &slen, hash, 20);
|
||||
|
||||
destroy_sensitive_data();
|
||||
|
||||
|
@ -1617,4 +1686,3 @@ ssh_dhgex_server(Kex *kex, Buffer *client_kexinit, Buffer *server_kexinit)
|
|||
/* have keys, free DH */
|
||||
DH_free(dh);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@ Port 22
|
|||
ListenAddress 0.0.0.0
|
||||
#ListenAddress ::
|
||||
HostKey /etc/ssh_host_key
|
||||
HostKey /etc/ssh_host_rsa_key
|
||||
HostKey /etc/ssh_host_dsa_key
|
||||
ServerKeyBits 768
|
||||
LoginGraceTime 600
|
||||
KeyRegenerationInterval 3600
|
||||
|
|
Loading…
Reference in New Issue