aboutsummaryrefslogtreecommitdiff
path: root/libssh
diff options
context:
space:
mode:
authorAris Adamantiadis <aris@0xbadc0de.be>2005-08-07 10:48:08 +0000
committerAris Adamantiadis <aris@0xbadc0de.be>2005-08-07 10:48:08 +0000
commit5c26ae735483d140f802d58b1872b2fe9468d219 (patch)
treee8e8e8dea72c371e15f6e510ecc97948a4139383 /libssh
parent3113d8756628f463fda33b93801aee3c6ee9aa32 (diff)
downloadlibssh-5c26ae735483d140f802d58b1872b2fe9468d219.tar.gz
libssh-5c26ae735483d140f802d58b1872b2fe9468d219.tar.xz
libssh-5c26ae735483d140f802d58b1872b2fe9468d219.zip
server kex done :)
git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@6 7dcaeef0-15fb-0310-b436-a5af3365683c
Diffstat (limited to 'libssh')
-rw-r--r--libssh/Makefile.in2
-rw-r--r--libssh/auth.c2
-rw-r--r--libssh/base64.c2
-rw-r--r--libssh/client.c12
-rw-r--r--libssh/dh.c203
-rw-r--r--libssh/kex.c18
-rw-r--r--libssh/keyfiles.c44
-rw-r--r--libssh/keys.c124
-rw-r--r--libssh/options.c49
-rw-r--r--libssh/packet.c7
-rw-r--r--libssh/server.c141
-rw-r--r--libssh/session.c4
-rw-r--r--libssh/wrapper.c59
13 files changed, 540 insertions, 127 deletions
diff --git a/libssh/Makefile.in b/libssh/Makefile.in
index ee6b5dd1..6eed8135 100644
--- a/libssh/Makefile.in
+++ b/libssh/Makefile.in
@@ -2,7 +2,7 @@
OBJECTS= client.o packet.o dh.o crypt.o connect.o error.o buffer.o \
string.o kex.o channels.o options.o keys.o auth.o base64.o \
keyfiles.o misc.o gzip.o wrapper.o sftp.o server.o crc32.o \
- session.o
+ session.o messages.o
SHELL = /bin/sh
VPATH = @srcdir@
diff --git a/libssh/auth.c b/libssh/auth.c
index 9819ecd0..938dff6b 100644
--- a/libssh/auth.c
+++ b/libssh/auth.c
@@ -1,6 +1,6 @@
/* auth.c deals with authentication methods */
/*
-Copyright 2003 Aris Adamantiadis
+Copyright 2003-2005 Aris Adamantiadis
This file is part of the SSH Library
diff --git a/libssh/base64.c b/libssh/base64.c
index 849c2ca5..1f0b415d 100644
--- a/libssh/base64.c
+++ b/libssh/base64.c
@@ -1,7 +1,7 @@
/* base64 contains the needed support for base64 alphabet system, */
/* as described in RFC1521 */
/*
-Copyright 2003,04 Aris Adamantiadis
+Copyright 2003-2005 Aris Adamantiadis
This file is part of the SSH Library
diff --git a/libssh/client.c b/libssh/client.c
index ef61115f..9411d5ec 100644
--- a/libssh/client.c
+++ b/libssh/client.c
@@ -104,7 +104,7 @@ int ssh_send_banner(SSH_SESSION *session,int server){
}
-int dh_handshake(SSH_SESSION *session){
+static int dh_handshake(SSH_SESSION *session){
STRING *e,*f,*pubkey,*signature;
packet_clear_out(session);
buffer_add_u8(session->out_buffer,SSH2_MSG_KEXDH_INIT);
@@ -186,6 +186,7 @@ int ssh_connect(SSH_SESSION *session){
ssh_set_error(session,SSH_FATAL,"Must set options before connect");
return -1;
}
+ session->client=1;
ssh_crypto_init();
if(options->fd==-1 && !options->host){
ssh_set_error(session,SSH_FATAL,"Hostname required");
@@ -222,7 +223,6 @@ int ssh_connect(SSH_SESSION *session){
ssh_set_error(session,SSH_FATAL,
"no version of SSH protocol usable (banner: %s)",
session->serverbanner);
- ssh_disconnect(session);
return -1;
}
}
@@ -231,19 +231,16 @@ int ssh_connect(SSH_SESSION *session){
switch(session->version){
case 2:
if(ssh_get_kex(session,0)){
- ssh_disconnect(session);
return -1;
}
set_status(options,0.6);
- list_kex(&session->server_kex);
+ ssh_list_kex(&session->server_kex);
if(set_kex(session)){
- ssh_disconnect(session);
return -1;
}
- send_kex(session,0);
+ ssh_send_kex(session,0);
set_status(options,0.8);
if(dh_handshake(session)){
- ssh_disconnect(session);
return -1;
}
set_status(options,1.0);
@@ -251,7 +248,6 @@ int ssh_connect(SSH_SESSION *session){
break;
case 1:
if(ssh_get_kex1(session)){
- ssh_disconnect(session);
return -1;
}
set_status(options,0.6);
diff --git a/libssh/dh.c b/libssh/dh.c
index 25bf5ae6..407fe97e 100644
--- a/libssh/dh.c
+++ b/libssh/dh.c
@@ -67,16 +67,12 @@ static bignum p;
/* maybe it might be enhanced .... */
/* XXX Do it. */
-void ssh_get_random(void *where, int len){
- static int rndfd=0;
- if(!rndfd){
- rndfd=open("/dev/urandom",O_RDONLY);
- if(rndfd<0){
- fprintf(stderr,"Can't open /dev/urandom\n");
- exit(-1);
- }
- }
- read(rndfd,where,len);
+int ssh_get_random(void *where, int len, int strong){
+ if(strong){
+ return RAND_bytes(where,len);
+ } else {
+ return RAND_pseudo_bytes(where,len);
+ }
}
/* it inits the values g and p which are used for DH key agreement */
@@ -101,11 +97,16 @@ void ssh_print_bignum(char *which,bignum num){
}
void ssh_print_hexa(char *descr,unsigned char *what, int len){
- int i;
- printf("%s : ",descr);
- for(i=0;i<len-1;i++)
- printf("%.2hhx:",what[i]);
- printf("%.2hhx\n",what[i]);
+ int i;
+ printf("%s : ",descr);
+ if(len>16)
+ printf ("\n ");
+ for(i=0;i<len-1;i++){
+ printf("%.2hhx:",what[i]);
+ if((i+1) % 16 ==0)
+ printf("\n ");
+ }
+ printf("%.2hhx\n",what[i]);
}
void dh_generate_x(SSH_SESSION *session){
@@ -116,7 +117,16 @@ void dh_generate_x(SSH_SESSION *session){
ssh_print_bignum("x",session->next_crypto->x);
#endif
}
-
+/* used by server */
+void dh_generate_y(SSH_SESSION *session){
+ session->next_crypto->y=bignum_new();
+ bignum_rand(session->next_crypto->y,128,0,-1);
+ /* not harder than this */
+#ifdef DEBUG_CRYPTO
+ ssh_print_bignum("y",session->next_crypto->y);
+#endif
+}
+/* used by server */
void dh_generate_e(SSH_SESSION *session){
bignum_CTX ctx=bignum_ctx_new();
session->next_crypto->e=bignum_new();
@@ -127,6 +137,15 @@ void dh_generate_e(SSH_SESSION *session){
bignum_ctx_free(ctx);
}
+void dh_generate_f(SSH_SESSION *session){
+ bignum_CTX ctx=bignum_ctx_new();
+ session->next_crypto->f=bignum_new();
+ bignum_mod_exp(session->next_crypto->f,g,session->next_crypto->y,p,ctx);
+#ifdef DEBUG_CRYPTO
+ ssh_print_bignum("f",session->next_crypto->f);
+#endif
+ bignum_ctx_free(ctx);
+}
STRING *make_bignum_string(bignum num){
STRING *ptr;
@@ -156,6 +175,11 @@ STRING *dh_get_e(SSH_SESSION *session){
return make_bignum_string(session->next_crypto->e);
}
+/* used by server */
+
+STRING *dh_get_f(SSH_SESSION *session){
+ return make_bignum_string(session->next_crypto->f);
+}
void dh_import_pubkey(SSH_SESSION *session,STRING *pubkey_string){
session->next_crypto->server_pubkey=pubkey_string;
}
@@ -167,10 +191,23 @@ void dh_import_f(SSH_SESSION *session,STRING *f_string){
#endif
}
+/* used by the server implementation */
+void dh_import_e(SSH_SESSION *session, STRING *e_string){
+ session->next_crypto->e=make_string_bn(e_string);
+#ifdef DEBUG_CRYPTO
+ ssh_print_bignum("e",session->next_crypto->e);
+#endif
+}
+
void dh_build_k(SSH_SESSION *session){
bignum_CTX ctx=bignum_ctx_new();
session->next_crypto->k=bignum_new();
- bignum_mod_exp(session->next_crypto->k,session->next_crypto->f,session->next_crypto->x,p,ctx);
+ /* the server and clients don't use the same numbers */
+ if(session->client){
+ bignum_mod_exp(session->next_crypto->k,session->next_crypto->f,session->next_crypto->x,p,ctx);
+ } else {
+ bignum_mod_exp(session->next_crypto->k,session->next_crypto->e,session->next_crypto->y,p,ctx);
+ }
#ifdef DEBUG_CRYPTO
ssh_print_bignum("shared secret key",session->next_crypto->k);
#endif
@@ -179,62 +216,95 @@ void dh_build_k(SSH_SESSION *session){
static void sha_add(STRING *str,SHACTX *ctx){
sha1_update(ctx,str,string_len(str)+4);
+#ifdef DEBUG_CRYPTO
+ ssh_print_hexa("partial hashed sessionid",str,string_len(str)+4);
+#endif
}
void make_sessionid(SSH_SESSION *session){
SHACTX *ctx;
STRING *num,*str;
- int len;
+ BUFFER *server_hash, *client_hash;
+ BUFFER *buf=buffer_new();
+ u32 len;
ctx=sha1_init();
str=string_from_char(session->clientbanner);
- sha_add(str,ctx);
+ buffer_add_ssh_string(buf,str);
+ //sha_add(str,ctx);
free(str);
str=string_from_char(session->serverbanner);
- sha_add(str,ctx);
+ buffer_add_ssh_string(buf,str);
+ //sha_add(str,ctx);
free(str);
-
- buffer_add_u32(session->in_hashbuf,0);
- buffer_add_u8(session->in_hashbuf,0);
- buffer_add_u32(session->out_hashbuf,0);
- buffer_add_u8(session->out_hashbuf,0);
-
- len=ntohl(buffer_get_len(session->out_hashbuf));
- sha1_update(ctx,&len,4);
-
- sha1_update(ctx,buffer_get(session->out_hashbuf),buffer_get_len(session->out_hashbuf));
- buffer_free(session->out_hashbuf);
- session->out_hashbuf=NULL;
-
- len=ntohl(buffer_get_len(session->in_hashbuf));
- sha1_update(ctx,&len,4);
-
- sha1_update(ctx,buffer_get(session->in_hashbuf),buffer_get_len(session->in_hashbuf));
- buffer_free(session->in_hashbuf);
+ if(session->client){
+ server_hash=session->in_hashbuf;
+ client_hash=session->out_hashbuf;
+ } else{
+ server_hash=session->out_hashbuf;
+ client_hash=session->in_hashbuf;
+ }
+ buffer_add_u32(server_hash,0);
+ buffer_add_u8(server_hash,0);
+ buffer_add_u32(client_hash,0);
+ buffer_add_u8(client_hash,0);
+
+ len=ntohl(buffer_get_len(client_hash));
+ //sha1_update(ctx,&len,4);
+ buffer_add_u32(buf,len);
+ buffer_add_data(buf,buffer_get(client_hash),buffer_get_len(client_hash));
+ //sha1_update(ctx,buffer_get(client_hash),buffer_get_len(client_hash));
+ buffer_free(client_hash);
+
+ len=ntohl(buffer_get_len(server_hash));
+ buffer_add_u32(buf,len);
+ //sha1_update(ctx,&len,4);
+
+ buffer_add_data(buf,buffer_get(server_hash),buffer_get_len(server_hash));
+// ssh_print_hexa("server_hash",buffer_get(server_hash),buffer_get_len(server_hash));
+ //sha1_update(ctx,buffer_get(server_hash),buffer_get_len(server_hash));
+ buffer_free(server_hash);
+
session->in_hashbuf=NULL;
- sha1_update(ctx,session->next_crypto->server_pubkey,len=(string_len(session->next_crypto->server_pubkey)+4));
+ session->out_hashbuf=NULL;
+ len=string_len(session->next_crypto->server_pubkey)+4;
+ buffer_add_data(buf,session->next_crypto->server_pubkey,len);
+// sha1_update(ctx,session->next_crypto->server_pubkey,len);
num=make_bignum_string(session->next_crypto->e);
- sha1_update(ctx,num,len=(string_len(num)+4));
+ len=string_len(num)+4;
+ buffer_add_data(buf,num,len);
+ //sha1_update(ctx,num,len);
free(num);
num=make_bignum_string(session->next_crypto->f);
- sha1_update(ctx,num,len=(string_len(num)+4));
+ len=string_len(num)+4;
+ buffer_add_data(buf,num,len);
+// sha1_update(ctx,num,len=(string_len(num)+4));
free(num);
num=make_bignum_string(session->next_crypto->k);
- sha1_update(ctx,num,len=(string_len(num)+4));
+ len=string_len(num)+4;
+ buffer_add_data(buf,num,len);
+// sha1_update(ctx,num,len);
free(num);
+#ifdef DEBUG_CRYPTO
+ ssh_print_hexa("hash buffer",buffer_get(buf),buffer_get_len(buf));
+#endif
+ sha1_update(ctx,buffer_get(buf),buffer_get_len(buf));
sha1_final(session->next_crypto->session_id,ctx);
-
+ buffer_free(buf);
#ifdef DEBUG_CRYPTO
- printf("Session hash : ");
- ssh_print_hexa("session id",session->next_crypto->session_id,SHA_DIGEST_LENGTH);
+ printf("Session hash : ");
+ ssh_print_hexa("session id",session->next_crypto->session_id,SHA_DIGEST_LENGTH);
#endif
}
void hashbufout_add_cookie(SSH_SESSION *session){
session->out_hashbuf=buffer_new();
buffer_add_u8(session->out_hashbuf,20);
- buffer_add_data(session->out_hashbuf,session->client_kex.cookie,16);
+ if(session->server)
+ buffer_add_data(session->out_hashbuf,session->server_kex.cookie,16);
+ else
+ buffer_add_data(session->out_hashbuf,session->client_kex.cookie,16);
}
@@ -259,12 +329,22 @@ void generate_session_keys(SSH_SESSION *session){
k_string=make_bignum_string(session->next_crypto->k);
/* IV */
- generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptIV,'A');
- generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptIV,'B');
-
- generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptkey,'C');
-
+ if(session->client){
+ generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptIV,'A');
+ generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptIV,'B');
+ } else {
+ generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptIV,'A');
+ generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptIV,'B');
+ }
+ if(session->client){
+ generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptkey,'C');
+ generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptkey,'D');
+ } else {
+ generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptkey,'C');
+ generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptkey,'D');
+ }
/* some ciphers need more than 20 bytes of input key */
+ /* XXX verify it's ok for server implementation */
if(session->next_crypto->out_cipher->keylen > SHA_DIGEST_LENGTH*8){
ctx=sha1_init();
sha1_update(ctx,k_string,string_len(k_string)+4);
@@ -273,8 +353,6 @@ void generate_session_keys(SSH_SESSION *session){
sha1_final(session->next_crypto->encryptkey+SHA_DIGEST_LEN,ctx);
}
- generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptkey,'D');
-
if(session->next_crypto->in_cipher->keylen > SHA_DIGEST_LENGTH*8){
ctx=sha1_init();
sha1_update(ctx,k_string,string_len(k_string)+4);
@@ -282,13 +360,17 @@ void generate_session_keys(SSH_SESSION *session){
sha1_update(ctx,session->next_crypto->decryptkey,SHA_DIGEST_LENGTH);
sha1_final(session->next_crypto->decryptkey+SHA_DIGEST_LEN,ctx);
}
-
- generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptMAC,'E');
- generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptMAC,'F');
+ if(session->client){
+ generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptMAC,'E');
+ generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptMAC,'F');
+ } else {
+ generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptMAC,'E');
+ generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptMAC,'F');
+ }
#ifdef DEBUG_CRYPTO
- ssh_print_hexa("client->server IV",session->next_crypto->encryptIV,SHA_DIGEST_LENGTH);
- ssh_print_hexa("server->client IV",session->next_crypto->decryptIV,SHA_DIGEST_LENGTH);
+ ssh_print_hexa("encrypt IV",session->next_crypto->encryptIV,SHA_DIGEST_LENGTH);
+ ssh_print_hexa("decrypt IV",session->next_crypto->decryptIV,SHA_DIGEST_LENGTH);
ssh_print_hexa("encryption key",session->next_crypto->encryptkey,16);
ssh_print_hexa("decryption key",session->next_crypto->decryptkey,16);
ssh_print_hexa("Encryption MAC",session->next_crypto->encryptMAC,SHA_DIGEST_LENGTH);
@@ -346,6 +428,9 @@ static int sig_verify(SSH_SESSION *session, PUBLIC_KEY *pubkey, SIGNATURE *signa
int valid=0;
char hash[SHA_DIGEST_LENGTH];
sha1(digest,SHA_DIGEST_LENGTH,hash);
+#ifdef DEBUG_CRYPTO
+ ssh_print_hexa("hash to be verified with dsa",hash,SHA_DIGEST_LENGTH);
+#endif
switch(pubkey->type){
case TYPE_DSS:
valid=DSA_do_verify(hash,SHA_DIGEST_LENGTH,signature->dsa_sign,
@@ -392,7 +477,7 @@ int signature_verify(SSH_SESSION *session,STRING *signature){
if(session->options->wanted_methods[SSH_HOSTKEYS]){
if(match(session->options->wanted_methods[SSH_HOSTKEYS],pubkey->type_c)){
ssh_set_error(session,SSH_FATAL,"Public key from server (%s) doesn't match user preference (%s)",
- pubkey->type,session->options->wanted_methods[SSH_HOSTKEYS]);
+ pubkey->type_c,session->options->wanted_methods[SSH_HOSTKEYS]);
publickey_free(pubkey);
return -1;
}
diff --git a/libssh/kex.c b/libssh/kex.c
index 4a8c30be..a7d3a175 100644
--- a/libssh/kex.c
+++ b/libssh/kex.c
@@ -37,7 +37,7 @@ MA 02111-1307, USA. */
#define AES ""
#endif
-#define DES "3des-cbc,"
+#define DES "3des-cbc"
#ifdef HAVE_LIBZ
#define ZLIB "none,zlib"
#else
@@ -121,7 +121,7 @@ char **space_tokenize(char *chain){
/* and a list of prefered objects (what_d) */
/* it will return a strduped pointer on the first prefered object found in the available objects list */
-static char *find_matching(char *in_d, char *what_d){
+char *ssh_find_matching(char *in_d, char *what_d){
char ** tok_in, **tok_what;
int i_in, i_what;
char *ret;
@@ -190,7 +190,7 @@ int ssh_get_kex(SSH_SESSION *session,int server_kex ){
return 0;
}
-void list_kex(KEX *kex){
+void ssh_list_kex(KEX *kex){
int i=0;
#ifdef DEBUG_CRYPTO
ssh_print_hexa("session cookie",kex->cookie,16);
@@ -214,13 +214,13 @@ int set_kex(SSH_SESSION *session){
if(options->wanted_cookie)
memcpy(client->cookie,options->wanted_cookie,16);
else
- ssh_get_random(client->cookie,16);
+ ssh_get_random(client->cookie,16,0);
client->methods=malloc(10 * sizeof(char **));
memset(client->methods,0,10*sizeof(char **));
for (i=0;i<10;i++){
if(!(wanted=options->wanted_methods[i]))
wanted=default_methods[i];
- client->methods[i]=find_matching(server->methods[i],wanted);
+ client->methods[i]=ssh_find_matching(server->methods[i],wanted);
if(!client->methods[i] && i < SSH_LANG_C_S){
ssh_set_error(session,SSH_FATAL,"kex error : did not find one of algos %s in list %s for %s",
wanted,server->methods[i],ssh_kex_nums[i]);
@@ -234,7 +234,7 @@ int set_kex(SSH_SESSION *session){
}
/* this function only sends the predefined set of kex methods */
-void send_kex(SSH_SESSION *session, int server_kex){
+void ssh_send_kex(SSH_SESSION *session, int server_kex){
STRING *str;
int i=0;
KEX *kex=(server_kex ? &session->server_kex : &session->client_kex);
@@ -242,7 +242,7 @@ void send_kex(SSH_SESSION *session, int server_kex){
buffer_add_u8(session->out_buffer,SSH2_MSG_KEXINIT);
buffer_add_data(session->out_buffer,kex->cookie,16);
hashbufout_add_cookie(session);
- list_kex(kex);
+ ssh_list_kex(kex);
for(i=0;i<10;i++){
str=string_from_char(kex->methods[i]);
buffer_add_ssh_string(session->out_hashbuf,str);
@@ -260,7 +260,7 @@ int verify_existing_algo(int algo, char *name){
char *ptr;
if(algo>9 || algo <0)
return -1;
- ptr=find_matching(supported_methods[algo],name);
+ ptr=ssh_find_matching(supported_methods[algo],name);
if(ptr){
free(ptr);
return 1;
@@ -303,7 +303,7 @@ STRING *encrypt_session_key(SSH_SESSION *session, PUBLIC_KEY *svrkey,
STRING *data1,*data2;
/* first, generate a session key */
- ssh_get_random(session->next_crypto->encryptkey,32);
+ ssh_get_random(session->next_crypto->encryptkey,32,1);
memcpy(buffer,session->next_crypto->encryptkey,32);
memcpy(session->next_crypto->decryptkey,
session->next_crypto->encryptkey,32);
diff --git a/libssh/keyfiles.c b/libssh/keyfiles.c
index 4891ab5a..93223538 100644
--- a/libssh/keyfiles.c
+++ b/libssh/keyfiles.c
@@ -74,7 +74,8 @@ PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session,char *filename,int type,
dsa=PEM_read_DSAPrivateKey(file,NULL,(void *)get_password_specified,passphrase);
fclose(file);
if(!dsa){
- ssh_set_error(session,SSH_FATAL,"parsing private key %s : %s",filename,ERR_error_string(ERR_get_error(),NULL));
+ ssh_set_error(session,SSH_FATAL,"parsing private key %s"
+ ": %s",filename,ERR_error_string(ERR_get_error(),NULL));
return NULL;
}
}
@@ -89,7 +90,8 @@ PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session,char *filename,int type,
rsa=PEM_read_RSAPrivateKey(file,NULL,(void *)get_password_specified,passphrase);
fclose(file);
if(!rsa){
- ssh_set_error(session,SSH_FATAL,"parsing private key %s : %s",filename,ERR_error_string(ERR_get_error(),NULL));
+ ssh_set_error(session,SSH_FATAL,"parsing private key %s"
+ ": %s",filename,ERR_error_string(ERR_get_error(),NULL));
return NULL;
}
} else {
@@ -104,6 +106,44 @@ PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session,char *filename,int type,
return privkey;
}
+/* same that privatekey_from_file() but without any passphrase things. */
+PRIVATE_KEY *_privatekey_from_file(void *session,char *filename,int type){
+ FILE *file=fopen(filename,"r");
+ PRIVATE_KEY *privkey;
+ DSA *dsa=NULL;
+ RSA *rsa=NULL;
+ if(!file){
+ ssh_set_error(session,SSH_REQUEST_DENIED,"Error opening %s : %s",filename,strerror(errno));
+ return NULL;
+ }
+ if(type==TYPE_DSS){
+ dsa=PEM_read_DSAPrivateKey(file,NULL,NULL,NULL);
+ fclose(file);
+ if(!dsa){
+ ssh_set_error(session,SSH_FATAL,"parsing private key %s"
+ ": %s",filename,ERR_error_string(ERR_get_error(),NULL));
+ return NULL;
+ }
+ }
+ else if (type==TYPE_RSA){
+ rsa=PEM_read_RSAPrivateKey(file,NULL,NULL,NULL);
+ fclose(file);
+ if(!rsa){
+ ssh_set_error(session,SSH_FATAL,"parsing private key %s"
+ ": %s",filename,ERR_error_string(ERR_get_error(),NULL));
+ return NULL;
+ }
+ } else {
+ ssh_set_error(session,SSH_FATAL,"Invalid private key type %d",type);
+ return NULL;
+ }
+ privkey=malloc(sizeof(PRIVATE_KEY));
+ privkey->type=type;
+ privkey->dsa_priv=dsa;
+ privkey->rsa_priv=rsa;
+ return privkey;
+}
+
void private_key_free(PRIVATE_KEY *prv){
if(prv->dsa_priv)
DSA_free(prv->dsa_priv);
diff --git a/libssh/keys.c b/libssh/keys.c
index 16a58db0..a5def00e 100644
--- a/libssh/keys.c
+++ b/libssh/keys.c
@@ -2,7 +2,7 @@
/* decoding a public key (both rsa and dsa), decoding a signature (rsa and dsa), veryfying them */
/*
-Copyright 2003,04 Aris Adamantiadis
+Copyright 2003-2005 Aris Adamantiadis
This file is part of the SSH Library
@@ -156,6 +156,77 @@ PUBLIC_KEY *publickey_from_string(STRING *pubkey_s){
return NULL;
}
+PUBLIC_KEY *publickey_from_privatekey(PRIVATE_KEY *prv){
+ PUBLIC_KEY *key=malloc(sizeof(PUBLIC_KEY));
+ key->type=prv->type;
+ switch(key->type){
+ case TYPE_DSS:
+ key->dsa_pub=DSA_new();
+ key->dsa_pub->p=BN_dup(prv->dsa_priv->p);
+ key->dsa_pub->q=BN_dup(prv->dsa_priv->q);
+ key->dsa_pub->pub_key=BN_dup(prv->dsa_priv->pub_key);
+ key->dsa_pub->g=BN_dup(prv->dsa_priv->g);
+ break;
+ case TYPE_RSA:
+ case TYPE_RSA1:
+ key->rsa_pub=RSA_new();
+ key->rsa_pub->e=BN_dup(prv->rsa_priv->e);
+ key->rsa_pub->n=BN_dup(prv->rsa_priv->n);
+ break;
+ }
+ key->type_c=ssh_type_to_char(prv->type);
+ return key;
+}
+
+static void dsa_public_to_string(DSA *key, BUFFER *buffer){
+ STRING *p,*q,*g,*n;
+ p=make_bignum_string(key->p);
+ q=make_bignum_string(key->q);
+ g=make_bignum_string(key->g);
+ n=make_bignum_string(key->pub_key);
+ buffer_add_ssh_string(buffer,p);
+ buffer_add_ssh_string(buffer,q);
+ buffer_add_ssh_string(buffer,g);
+ buffer_add_ssh_string(buffer,n);
+ free(p);
+ free(q);
+ free(g);
+ free(n);
+}
+
+static void rsa_public_to_string(RSA *key, BUFFER *buffer){
+ STRING *e, *n;
+ e=make_bignum_string(key->e);
+ n=make_bignum_string(key->n);
+ buffer_add_ssh_string(buffer,e);
+ buffer_add_ssh_string(buffer,n);
+ free(e);
+ free(n);
+}
+
+STRING *publickey_to_string(PUBLIC_KEY *key){
+ STRING *type;
+ STRING *ret;
+ BUFFER *buf;
+ type=string_from_char(ssh_type_to_char(key->type));
+ buf=buffer_new();
+ buffer_add_ssh_string(buf,type);
+ switch(key->type){
+ case TYPE_DSS:
+ dsa_public_to_string(key->dsa_pub,buf);
+ break;
+ case TYPE_RSA:
+ case TYPE_RSA1:
+ rsa_public_to_string(key->rsa_pub,buf);
+ break;
+ }
+ ret=string_new(buffer_get_len(buf));
+ string_fill(ret,buffer_get(buf),buffer_get_len(buf));
+ buffer_free(buf);
+ free(type);
+ return ret;
+}
+
/* Signature decoding functions */
STRING *signature_to_string(SIGNATURE *sign){
@@ -325,22 +396,31 @@ static STRING *RSA_do_sign(void *payload,int len,RSA *privkey){
return sign;
}
+/* this function signs the session id (known as H) as a string then the content of sigbuf */
STRING *ssh_do_sign(SSH_SESSION *session,BUFFER *sigbuf, PRIVATE_KEY *privatekey){
SHACTX *ctx;
STRING *session_str=string_new(SHA_DIGEST_LEN);
char hash[SHA_DIGEST_LEN];
SIGNATURE *sign;
STRING *signature;
- string_fill(session_str,session->current_crypto->session_id,SHA_DIGEST_LENGTH);
+ CRYPTO *crypto=session->current_crypto?session->current_crypto:session->next_crypto;
+ string_fill(session_str,crypto->session_id,SHA_DIGEST_LENGTH);
ctx=sha1_init();
sha1_update(ctx,session_str,string_len(session_str)+4);
sha1_update(ctx,buffer_get(sigbuf),buffer_get_len(sigbuf));
sha1_final(hash,ctx);
+#ifdef DEBUG_CRYPTO
+ ssh_print_hexa("Hash being signed with dsa",hash,SHA_DIGEST_LENGTH);
+#endif
free(session_str);
sign=malloc(sizeof(SIGNATURE));
switch(privatekey->type){
case TYPE_DSS:
sign->dsa_sign=DSA_do_sign(hash,SHA_DIGEST_LENGTH,privatekey->dsa_priv);
+#ifdef DEBUG_CRYPTO
+ ssh_print_bignum("r",sign->dsa_sign->r);
+ ssh_print_bignum("s",sign->dsa_sign->s);
+#endif
sign->rsa_sign=NULL;
break;
case TYPE_RSA:
@@ -368,3 +448,43 @@ STRING *ssh_encrypt_rsa1(SSH_SESSION *session, STRING *data, PUBLIC_KEY *key){
return ret;
}
+
+/* this function signs the session id */
+STRING *ssh_sign_session_id(SSH_SESSION *session, PRIVATE_KEY *privatekey){
+ SHACTX *ctx;
+ char hash[SHA_DIGEST_LEN];
+ SIGNATURE *sign;
+ STRING *signature;
+ CRYPTO *crypto=session->current_crypto?session->current_crypto:session->next_crypto;
+ ctx=sha1_init();
+ sha1_update(ctx,crypto->session_id,SHA_DIGEST_LENGTH);
+ sha1_final(hash,ctx);
+#ifdef DEBUG_CRYPTO
+ ssh_print_hexa("Hash being signed with dsa",hash,SHA_DIGEST_LENGTH);
+#endif
+ sign=malloc(sizeof(SIGNATURE));
+ switch(privatekey->type){
+ case TYPE_DSS:
+ sign->dsa_sign=DSA_do_sign(hash,SHA_DIGEST_LENGTH,privatekey->dsa_priv);
+#ifdef DEBUG_CRYPTO
+ ssh_print_bignum("r",sign->dsa_sign->r);
+ ssh_print_bignum("s",sign->dsa_sign->s);
+#endif
+ sign->rsa_sign=NULL;
+ break;
+ case TYPE_RSA:
+ sign->rsa_sign=RSA_do_sign(hash,SHA_DIGEST_LENGTH,privatekey->rsa_priv);
+ sign->dsa_sign=NULL;
+ break;
+ }
+ sign->type=privatekey->type;
+ if(!sign->dsa_sign && !sign->rsa_sign){
+ ssh_set_error(session,SSH_FATAL,"Signing : openssl error");
+ signature_free(sign);
+ return NULL;
+ }
+ signature=signature_to_string(sign);
+ signature_free(sign);
+ return signature;
+}
+
diff --git a/libssh/options.c b/libssh/options.c
index bde7f5e4..e1c166d5 100644
--- a/libssh/options.c
+++ b/libssh/options.c
@@ -43,33 +43,37 @@ void ssh_options_set_port(SSH_OPTIONS *opt, unsigned int port){
opt->port=port&0xffff;
}
SSH_OPTIONS *ssh_options_copy(SSH_OPTIONS *opt){
- SSH_OPTIONS *ret=ssh_options_new();
+ SSH_OPTIONS *ret=ssh_options_new();
int i;
- ret->fd=opt->fd;
+ ret->fd=opt->fd;
ret->port=opt->port;
if(opt->username)
- ret->username=strdup(opt->username);
+ ret->username=strdup(opt->username);
if(opt->host)
- ret->host=strdup(opt->host);
+ ret->host=strdup(opt->host);
if(opt->bindaddr)
- ret->host=strdup(opt->bindaddr);
+ ret->host=strdup(opt->bindaddr);
if(opt->identity)
- ret->identity=strdup(opt->identity);
+ ret->identity=strdup(opt->identity);
if(opt->ssh_dir)
ret->ssh_dir=strdup(opt->ssh_dir);
- if(opt->known_hosts_file)
- ret->known_hosts_file=strdup(opt->known_hosts_file);
- for(i=0;i<10;++i)
- if(opt->wanted_methods[i])
- ret->wanted_methods[i]=strdup(opt->wanted_methods[i]);
- ret->passphrase_function=opt->passphrase_function;
- ret->connect_status_function=opt->connect_status_function;
- ret->connect_status_arg=opt->connect_status_arg;
- ret->timeout=opt->timeout;
- ret->timeout_usec=opt->timeout_usec;
+ if(opt->known_hosts_file)
+ ret->known_hosts_file=strdup(opt->known_hosts_file);
+ if(opt->dsakey)
+ ret->dsakey=strdup(opt->dsakey);
+ if(opt->rsakey)
+ ret->rsakey=strdup(opt->rsakey);
+ for(i=0;i<10;++i)
+ if(opt->wanted_methods[i])
+ ret->wanted_methods[i]=strdup(opt->wanted_methods[i]);
+ ret->passphrase_function=opt->passphrase_function;
+ ret->connect_status_function=opt->connect_status_function;
+ ret->connect_status_arg=opt->connect_status_arg;
+ ret->timeout=opt->timeout;
+ ret->timeout_usec=opt->timeout_usec;
ret->ssh2allowed=opt->ssh2allowed;
ret->ssh1allowed=opt->ssh1allowed;
- return ret;
+ return ret;
}
void ssh_options_free(SSH_OPTIONS *opt){
@@ -85,6 +89,10 @@ void ssh_options_free(SSH_OPTIONS *opt){
free(opt->bindaddr);
if(opt->ssh_dir)
free(opt->ssh_dir);
+ if(opt->dsakey)
+ free(opt->dsakey);
+ if(opt->rsakey)
+ free(opt->rsakey);
for(i=0;i<10;i++)
if(opt->wanted_methods[i])
free(opt->wanted_methods[i]);
@@ -142,6 +150,13 @@ void ssh_options_set_identity(SSH_OPTIONS *opt, char *identity){
opt->identity=strdup(buffer);
}
+void ssh_options_set_dsa_server_key(SSH_OPTIONS *opt, char *dsakey){
+ opt->dsakey=strdup(dsakey);
+}
+void ssh_options_set_rsa_server_key(SSH_OPTIONS *opt, char *rsakey){
+ opt->rsakey=strdup(rsakey);
+}
+
void ssh_options_set_banner(SSH_OPTIONS *opt, char *banner){
if(opt->banner)
free(opt->banner);
diff --git a/libssh/packet.c b/libssh/packet.c
index 89132f9c..0f86f61a 100644
--- a/libssh/packet.c
+++ b/libssh/packet.c
@@ -138,7 +138,7 @@ static int packet_read2(SSH_SESSION *session){
ssh_set_error(session,SSH_FATAL,"Packet too short to read padding");
return -1;
}
- ssh_say(3,"%hhd bytes padding\n",padding);
+ ssh_say(3,"%hhd bytes padding, %d bytes left in buffer\n",padding,buffer_get_rest_len(session->in_buffer));
if(padding > buffer_get_rest_len(session->in_buffer)){
ssh_set_error(session,SSH_FATAL,"invalid padding: %d (%d resting)",padding,buffer_get_rest_len(session->in_buffer));
#ifdef DEBUG_CRYPTO
@@ -147,8 +147,10 @@ static int packet_read2(SSH_SESSION *session){
return -1;
}
buffer_pass_bytes_end(session->in_buffer,padding);
+ ssh_say(3,"After padding, %d bytes left in buffer\n",buffer_get_rest_len(session->in_buffer));
#ifdef HAVE_LIBZ
if(session->current_crypto && session->current_crypto->do_compress_in){
+ ssh_say(3,"Decompressing ...\n");
decompress_buffer(session,session->in_buffer);
}
#endif
@@ -320,6 +322,7 @@ static int packet_send2(SSH_SESSION *session){
ssh_say(3,"Writing on the wire a packet having %ld bytes before",currentlen);
#ifdef HAVE_LIBZ
if(session->current_crypto && session->current_crypto->do_compress_out){
+ ssh_say(3,"Compressing ...\n");
compress_buffer(session,session->out_buffer);
currentlen=buffer_get_len(session->out_buffer);
}
@@ -328,7 +331,7 @@ static int packet_send2(SSH_SESSION *session){
if(padding<4)
padding+=blocksize;
if(session->current_crypto)
- ssh_get_random(padstring,padding);
+ ssh_get_random(padstring,padding,0);
else
memset(padstring,0,padding);
finallen=htonl(currentlen+padding+1);
diff --git a/libssh/server.c b/libssh/server.c
index 25f760ad..62294436 100644
--- a/libssh/server.c
+++ b/libssh/server.c
@@ -1,9 +1,6 @@
/* server.c */
-
-/* No. It doesn't work yet. It's just hard to have 2 separated trees, one for releases
- * and one for development */
/*
-Copyright 2004 Aris Adamantiadis
+Copyright 2004,2005 Aris Adamantiadis
This file is part of the SSH Library
@@ -35,6 +32,7 @@ MA 02111-1307, USA. */
#include <string.h>
#include "libssh/libssh.h"
#include "libssh/server.h"
+#include "libssh/ssh2.h"
static int bind_socket(SSH_BIND *ssh_bind,char *hostname, int port) {
struct sockaddr_in myaddr;
int opt = 1;
@@ -113,55 +111,79 @@ void ssh_bind_fd_toaccept(SSH_BIND *ssh_bind){
SSH_SESSION *ssh_bind_accept(SSH_BIND *ssh_bind){
SSH_SESSION *session;
+ PRIVATE_KEY *dsa=NULL, *rsa=NULL;
if(ssh_bind->bindfd<0){
ssh_set_error(ssh_bind,SSH_FATAL,"Can't accept new clients on a "
"not bound socket.");
return NULL;
}
+ if(!ssh_bind->options->dsakey && !ssh_bind->options->rsakey){
+ ssh_set_error(ssh_bind,SSH_FATAL,"DSA or RSA host key file must be set before accept()");
+ return NULL;
+ }
+ if(ssh_bind->options->dsakey){
+ dsa=_privatekey_from_file(ssh_bind,ssh_bind->options->dsakey,TYPE_DSS);
+ if(!dsa)
+ return NULL;
+ ssh_say(2,"Dsa private key read successfuly\n");
+ }
+ if(ssh_bind->options->rsakey){
+ rsa=_privatekey_from_file(ssh_bind,ssh_bind->options->rsakey,TYPE_RSA);
+ if(!rsa){
+ if(dsa)
+ private_key_free(dsa);
+ return NULL;
+ }
+ ssh_say(2,"RSA private key read successfuly\n");
+ }
int fd=accept(ssh_bind->bindfd,NULL,NULL);
if(fd<0){
ssh_set_error(ssh_bind,SSH_FATAL,"Accepting a new connection: %s",
strerror(errno));
+ if(dsa)
+ private_key_free(dsa);
+ if(rsa)
+ private_key_free(rsa);
return NULL;
}
- session=ssh_new(ssh_options_copy(ssh_bind->options));
+ session=ssh_new();
session->server=1;
+ session->version=2;
session->fd=fd;
session->options=ssh_options_copy(ssh_bind->options);
+ session->dsa_key=dsa;
+ session->rsa_key=rsa;
return session;
}
-
-/* do the banner and key exchange */
-int ssh_accept(SSH_SESSION *session){
- ssh_send_banner(session,1);
- return 0;
-}
-
-/*
extern char *supported_methods[];
+
int server_set_kex(SSH_SESSION * session) {
KEX *server = &session->server_kex;
SSH_OPTIONS *options = session->options;
int i;
char *wanted;
- if (!options) {
- ssh_set_error(session, SSH_FATAL,
- "Options structure is null(client's bug)");
- return -1;
- }
memset(server,0,sizeof(KEX));
// the program might ask for a specific cookie to be sent. useful for server
// debugging
if (options->wanted_cookie)
memcpy(server->cookie, options->wanted_cookie, 16);
else
- ssh_get_random(server->cookie, 16);
+ ssh_get_random(server->cookie, 16,0);
+ if(session->dsa_key && session->rsa_key){
+ ssh_options_set_wanted_algos(options,SSH_HOSTKEYS,"ssh-dss,ssh-rsa");
+ } else {
+ if(session->dsa_key)
+ ssh_options_set_wanted_algos(options,SSH_HOSTKEYS,"ssh-dss");
+ else
+ ssh_options_set_wanted_algos(options,SSH_HOSTKEYS,"ssh-rsa");
+ }
server->methods = malloc(10 * sizeof(char **));
for (i = 0; i < 10; i++) {
- if (!(wanted = options->wanted_methods[i]))
- wanted = supported_methods[i];
- server->methods[i] = wanted;
- printf("server->methods[%d]=%s\n",i,wanted);
+ if (!(wanted = options->wanted_methods[i]))
+ wanted = supported_methods[i];
+ server->methods[i] = wanted;
+ printf("server->methods[%d]=%s\n",i,wanted);
+ }
if (!server->methods[i]) {
ssh_set_error(session, SSH_FATAL,
"kex error : did not find algo");
@@ -170,5 +192,76 @@ int server_set_kex(SSH_SESSION * session) {
return 0;
}
-*/
+static int dh_handshake_server(SSH_SESSION *session){
+ STRING *e,*f,*pubkey,*sign;
+ PUBLIC_KEY *pub;
+ PRIVATE_KEY *prv;
+ BUFFER *buf=buffer_new();
+ if(packet_wait(session, SSH2_MSG_KEXDH_INIT ,1))
+ return -1;
+ e=buffer_get_ssh_string(session->in_buffer);
+ if(!e){
+ ssh_set_error(session,SSH_FATAL,"No e number in client request");
+ return -1;
+ }
+ dh_import_e(session,e);
+ dh_generate_y(session);
+ dh_generate_f(session);
+ f=dh_get_f(session);
+ switch(session->hostkeys){
+ case TYPE_DSS:
+ prv=session->dsa_key;
+ break;
+ case TYPE_RSA:
+ prv=session->rsa_key;
+ break;
+ }
+ pub=publickey_from_privatekey(prv);
+ pubkey=publickey_to_string(pub);
+ publickey_free(pub);
+ dh_import_pubkey(session,pubkey);
+ dh_build_k(session);
+ make_sessionid(session);
+ sign=ssh_sign_session_id(session,prv);
+ buffer_free(buf);
+ private_key_free(prv);
+ buffer_add_u8(session->out_buffer,SSH2_MSG_KEXDH_REPLY);
+ buffer_add_ssh_string(session->out_buffer,pubkey);
+ buffer_add_ssh_string(session->out_buffer,f);
+ buffer_add_ssh_string(session->out_buffer,sign);
+ free(sign);
+ packet_send(session);
+ free(f);
+ packet_clear_out(session);
+ buffer_add_u8(session->out_buffer,SSH2_MSG_NEWKEYS);
+ packet_send(session);
+ ssh_say(2,"SSH_MSG_NEWKEYS sent\n");
+
+ packet_wait(session,SSH2_MSG_NEWKEYS,1);
+ ssh_say(2,"Got SSH_MSG_NEWKEYS\n");
+ generate_session_keys(session);
+ /* once we got SSH2_MSG_NEWKEYS we can switch next_crypto and current_crypto */
+ if(session->current_crypto)
+ crypto_free(session->current_crypto);
+ /* XXX later, include a function to change keys */
+ session->current_crypto=session->next_crypto;
+ session->next_crypto=crypto_new();
+ return 0;
+}
+/* do the banner and key exchange */
+int ssh_accept(SSH_SESSION *session){
+ ssh_send_banner(session,1);
+ ssh_crypto_init();
+ session->clientbanner=ssh_get_banner(session);
+ server_set_kex(session);
+ ssh_send_kex(session,1);
+ if(ssh_get_kex(session,1))
+ return -1;
+ ssh_list_kex(&session->client_kex);
+ crypt_set_algorithms_server(session);
+ if(dh_handshake_server(session))
+ return -1;
+ session->connected=1;
+ return 0;
+}
diff --git a/libssh/session.c b/libssh/session.c
index bfc6e58e..1ea071e0 100644
--- a/libssh/session.c
+++ b/libssh/session.c
@@ -67,6 +67,10 @@ void ssh_cleanup(SSH_SESSION *session){
free(session->server_kex.methods[i]);
free(session->client_kex.methods);
free(session->server_kex.methods);
+ if(session->dsa_key)
+ private_key_free(session->dsa_key);
+ if(session->rsa_key)
+ private_key_free(session->rsa_key);
memset(session,'X',sizeof(SSH_SESSION)); /* burn connection, it could hangs
sensitive datas */
free(session);
diff --git a/libssh/wrapper.c b/libssh/wrapper.c
index 1c49ed79..9d418df0 100644
--- a/libssh/wrapper.c
+++ b/libssh/wrapper.c
@@ -299,7 +299,6 @@ static int crypt_set_algorithms2(SSH_SESSION *session){
}
ssh_say(2,"Set input algorithm %s\n",wanted);
session->next_crypto->in_cipher=cipher_new(i);
-
/* compression */
if(strstr(session->client_kex.methods[SSH_COMP_C_S],"zlib"))
session->next_crypto->do_compress_out=1;
@@ -327,3 +326,61 @@ int crypt_set_algorithms(SSH_SESSION *session){
crypt_set_algorithms2(session);
}
+int crypt_set_algorithms_server(SSH_SESSION *session){
+ /* we must scan the kex entries to find crypto algorithms and set their appropriate structure */
+ int i=0;
+ /* out */
+ char *server=session->server_kex.methods[SSH_CRYPT_S_C];
+ char *client=session->client_kex.methods[SSH_CRYPT_S_C];
+ char *match=ssh_find_matching(client,server);
+ while(ssh_ciphertab[i].name && strcmp(match,ssh_ciphertab[i].name))
+ i++;
+ if(!ssh_ciphertab[i].name){
+ ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms : no crypto algorithm function found for %s",server);
+ return -1;
+ }
+ ssh_say(2,"Set output algorithm %s\n",match);
+ session->next_crypto->out_cipher=cipher_new(i);
+ i=0;
+ /* in */
+ client=session->client_kex.methods[SSH_CRYPT_C_S];
+ server=session->server_kex.methods[SSH_CRYPT_S_C];
+ match=ssh_find_matching(client,server);
+ while(ssh_ciphertab[i].name && strcmp(match,ssh_ciphertab[i].name))
+ i++;
+ if(!ssh_ciphertab[i].name){
+ ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms : no crypto algorithm function found for %s",server);
+ return -1;
+ }
+ ssh_say(2,"Set input algorithm %s\n",match);
+ session->next_crypto->in_cipher=cipher_new(i);
+ /* compression */
+ client=session->client_kex.methods[SSH_CRYPT_C_S];
+ server=session->server_kex.methods[SSH_CRYPT_C_S];
+ match=ssh_find_matching(client,server);
+ if(match && !strcmp(match,"zlib")){
+ ssh_say(2,"enabling C->S compression\n");
+ session->next_crypto->do_compress_in=1;
+ }
+
+ client=session->client_kex.methods[SSH_CRYPT_S_C];
+ server=session->server_kex.methods[SSH_CRYPT_S_C];
+ match=ssh_find_matching(client,server);
+ if(match && !strcmp(match,"zlib")){
+ ssh_say(2,"enabling S->C compression\n");
+ session->next_crypto->do_compress_out=1;
+ }
+
+ server=session->server_kex.methods[SSH_HOSTKEYS];
+ client=session->client_kex.methods[SSH_HOSTKEYS];
+ match=ssh_find_matching(client,server);
+ if(!strcmp(match,"ssh-dss"))
+ session->hostkeys=TYPE_DSS;
+ else if(!strcmp(match,"ssh-rsa"))
+ session->hostkeys=TYPE_RSA;
+ else {
+ ssh_set_error(session,SSH_FATAL,"cannot know what %s is into %s",match,server);
+ return -1;
+ }
+ return 0;
+}