mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-12-02 01:17:52 +03:00
Added support for known_hosts format version 1
git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@51 7dcaeef0-15fb-0310-b436-a5af3365683c
This commit is contained in:
@@ -73,6 +73,8 @@ typedef gcry_mpi_t bignum;
|
|||||||
#define bignum_free(num) gcry_mpi_release(num)
|
#define bignum_free(num) gcry_mpi_release(num)
|
||||||
#define bignum_set_word(bn,n) gcry_mpi_set_ui(bn,n)
|
#define bignum_set_word(bn,n) gcry_mpi_set_ui(bn,n)
|
||||||
#define bignum_bin2bn(bn,datalen,data) gcry_mpi_scan(data,GCRYMPI_FMT_USG,bn,datalen,NULL)
|
#define bignum_bin2bn(bn,datalen,data) gcry_mpi_scan(data,GCRYMPI_FMT_USG,bn,datalen,NULL)
|
||||||
|
#define bignum_bn2dec(num) my_gcry_bn2dec(num)
|
||||||
|
#define bignum_dec2bn(num, data) my_gcry_dec2bn(data, num)
|
||||||
#define bignum_bn2hex(num,data) gcry_mpi_aprint(GCRYMPI_FMT_HEX,data,NULL,num)
|
#define bignum_bn2hex(num,data) gcry_mpi_aprint(GCRYMPI_FMT_HEX,data,NULL,num)
|
||||||
#define bignum_hex2bn(num,datalen,data) gcry_mpi_scan(num,GCRYMPI_FMT_HEX,data,datalen,NULL)
|
#define bignum_hex2bn(num,datalen,data) gcry_mpi_scan(num,GCRYMPI_FMT_HEX,data,datalen,NULL)
|
||||||
#define bignum_rand(num,bits) gcry_mpi_randomize(num,bits,GCRY_STRONG_RANDOM),gcry_mpi_set_bit(num,bits-1),gcry_mpi_set_bit(num,0)
|
#define bignum_rand(num,bits) gcry_mpi_randomize(num,bits,GCRY_STRONG_RANDOM),gcry_mpi_set_bit(num,bits-1),gcry_mpi_set_bit(num,0)
|
||||||
@@ -108,6 +110,8 @@ typedef BN_CTX* bignum_CTX;
|
|||||||
#define bignum_free(num) BN_clear_free(num)
|
#define bignum_free(num) BN_clear_free(num)
|
||||||
#define bignum_set_word(bn,n) BN_set_word(bn,n)
|
#define bignum_set_word(bn,n) BN_set_word(bn,n)
|
||||||
#define bignum_bin2bn(bn,datalen,data) BN_bin2bn(bn,datalen,data)
|
#define bignum_bin2bn(bn,datalen,data) BN_bin2bn(bn,datalen,data)
|
||||||
|
#define bignum_bn2dec(num) BN_bn2dec(num)
|
||||||
|
#define bignum_dec2bn(bn,data) BN_dec2bn(data,bn)
|
||||||
#define bignum_bn2hex(num) BN_bn2hex(num)
|
#define bignum_bn2hex(num) BN_bn2hex(num)
|
||||||
#define bignum_rand(rnd, bits, top, bottom) BN_rand(rnd,bits,top,bottom)
|
#define bignum_rand(rnd, bits, top, bottom) BN_rand(rnd,bits,top,bottom)
|
||||||
#define bignum_ctx_new() BN_CTX_new()
|
#define bignum_ctx_new() BN_CTX_new()
|
||||||
@@ -532,6 +536,12 @@ int channel_write1(CHANNEL *channel, void *data, int len);
|
|||||||
|
|
||||||
int ssh_handle_packets(SSH_SESSION *session);
|
int ssh_handle_packets(SSH_SESSION *session);
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBGCRYPT
|
||||||
|
/* gcrypt_missing.c */
|
||||||
|
int my_gcry_dec2bn(bignum *bn, const char *data);
|
||||||
|
char *my_gcry_bn2dec(bignum bn);
|
||||||
|
#endif /* !HAVE_LIBGCRYPT */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} ;
|
} ;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
OBJECTS= client.o packet.o dh.o crypt.o connect.o error.o buffer.o \
|
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 \
|
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 \
|
keyfiles.o misc.o gzip.o wrapper.o sftp.o server.o crc32.o \
|
||||||
session.o messages.o channels1.o auth1.o sftpserver.o
|
session.o messages.o channels1.o auth1.o sftpserver.o \
|
||||||
|
gcrypt_missing.o
|
||||||
SHELL = /bin/sh
|
SHELL = /bin/sh
|
||||||
VPATH = @srcdir@
|
VPATH = @srcdir@
|
||||||
|
|
||||||
|
|||||||
78
libssh/gcrypt_missing.c
Normal file
78
libssh/gcrypt_missing.c
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
/* gcrypt_missing.c */
|
||||||
|
/* This part of the library handles private and public key files needed for publickey authentication,*/
|
||||||
|
/* as well as servers public hashes verifications and certifications. Lot of code here handles openssh */
|
||||||
|
/* implementations (key files aren't standardized yet). */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2003,04 Aris Adamantiadis
|
||||||
|
|
||||||
|
This file is part of the SSH Library
|
||||||
|
|
||||||
|
The SSH Library is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
The SSH Library is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with the SSH Library; see the file COPYING. If not, write to
|
||||||
|
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||||
|
MA 02111-1307, USA. */
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "libssh/priv.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBGCRYPT
|
||||||
|
int my_gcry_dec2bn(bignum *bn, const char *data)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
|
||||||
|
*bn = bignum_new();
|
||||||
|
gcry_mpi_set_ui(*bn, 0);
|
||||||
|
for (count = 0; data[count]; ++count)
|
||||||
|
{
|
||||||
|
gcry_mpi_mul_ui(*bn, *bn, 10);
|
||||||
|
gcry_mpi_add_ui(*bn, *bn, data[count] - '0');
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *my_gcry_bn2dec(bignum bn)
|
||||||
|
{
|
||||||
|
int count, count2;
|
||||||
|
int size, rsize;
|
||||||
|
char *ret;
|
||||||
|
bignum bndup, num, ten;
|
||||||
|
char decnum;
|
||||||
|
|
||||||
|
size = gcry_mpi_get_nbits(bn) * 3;
|
||||||
|
rsize = size / 10 + size / 1000 + 2;
|
||||||
|
ret = malloc(rsize + 1);
|
||||||
|
if (!gcry_mpi_cmp_ui(bn, 0))
|
||||||
|
strcpy(ret, "0");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (bndup = gcry_mpi_copy(bn), ten = bignum_new(), num = bignum_new(),
|
||||||
|
bignum_set_word(ten, 10), count = rsize; count; --count)
|
||||||
|
{
|
||||||
|
gcry_mpi_div(bndup, num, bndup, ten, 0);
|
||||||
|
for (decnum = 0, count2 = gcry_mpi_get_nbits(num); count2; decnum *= 2,
|
||||||
|
decnum += (gcry_mpi_test_bit(num, count2 - 1) ? 1 : 0), --count2)
|
||||||
|
;
|
||||||
|
ret[count - 1] = decnum + '0';
|
||||||
|
}
|
||||||
|
for (count = 0; count < rsize && ret[count] == '0'; ++count)
|
||||||
|
;
|
||||||
|
for (count2 = 0; count2 < rsize - count; ++count2)
|
||||||
|
ret[count2] = ret[count2 + count];
|
||||||
|
ret[count2] = 0;
|
||||||
|
bignum_free(num);
|
||||||
|
bignum_free(bndup);
|
||||||
|
bignum_free(ten);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
15
libssh/kex.c
15
libssh/kex.c
@@ -312,22 +312,29 @@ static void build_session_id1(SSH_SESSION *session, STRING *servern,
|
|||||||
static int modulus_smaller(PUBLIC_KEY *k1, PUBLIC_KEY *k2){
|
static int modulus_smaller(PUBLIC_KEY *k1, PUBLIC_KEY *k2){
|
||||||
bignum n1;
|
bignum n1;
|
||||||
bignum n2;
|
bignum n2;
|
||||||
|
int res;
|
||||||
#ifdef HAVE_LIBGCRYPT
|
#ifdef HAVE_LIBGCRYPT
|
||||||
gcry_sexp_t sexp;
|
gcry_sexp_t sexp;
|
||||||
sexp=gcry_sexp_find_token(k1->rsa_pub,"n",0);
|
sexp=gcry_sexp_find_token(k1->rsa_pub,"n",0);
|
||||||
n1=gcry_sexp_nth_mpi(sexp,1,GCRYMPI_FMT_STD);
|
n1=gcry_sexp_nth_mpi(sexp,1,GCRYMPI_FMT_USG);
|
||||||
gcry_sexp_release(sexp);
|
gcry_sexp_release(sexp);
|
||||||
sexp=gcry_sexp_find_token(k2->rsa_pub,"n",0);
|
sexp=gcry_sexp_find_token(k2->rsa_pub,"n",0);
|
||||||
n2=gcry_sexp_nth_mpi(sexp,1,GCRYMPI_FMT_STD);
|
n2=gcry_sexp_nth_mpi(sexp,1,GCRYMPI_FMT_USG);
|
||||||
gcry_sexp_release(sexp);
|
gcry_sexp_release(sexp);
|
||||||
#elif defined HAVE_LIBCRYPTO
|
#elif defined HAVE_LIBCRYPTO
|
||||||
n1=k1->rsa_pub->n;
|
n1=k1->rsa_pub->n;
|
||||||
n2=k2->rsa_pub->n;
|
n2=k2->rsa_pub->n;
|
||||||
#endif
|
#endif
|
||||||
if(bignum_cmp(n1,n2)<0)
|
if(bignum_cmp(n1,n2)<0)
|
||||||
return 1;
|
res=1;
|
||||||
else
|
else
|
||||||
return 0;
|
res=0;
|
||||||
|
#ifdef HAVE_LIBGCRYPT
|
||||||
|
bignum_free(n1);
|
||||||
|
bignum_free(n2);
|
||||||
|
#endif
|
||||||
|
return res;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ABS(A) ( (A)<0 ? -(A):(A) )
|
#define ABS(A) ( (A)<0 ? -(A):(A) )
|
||||||
|
|||||||
@@ -29,7 +29,9 @@ MA 02111-1307, USA. */
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "libssh/priv.h"
|
#include "libssh/priv.h"
|
||||||
#ifdef HAVE_LIBCRYPTO
|
#ifdef HAVE_LIBGCRYPT
|
||||||
|
#include <gcrypt.h>
|
||||||
|
#elif defined HAVE_LIBCRYPTO
|
||||||
#include <openssl/pem.h>
|
#include <openssl/pem.h>
|
||||||
#include <openssl/dsa.h>
|
#include <openssl/dsa.h>
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
@@ -732,6 +734,15 @@ STRING *publickey_from_next_file(SSH_SESSION *session,char **pub_keys_path,char
|
|||||||
return pubkey;
|
return pubkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int alldigits(char *s)
|
||||||
|
{
|
||||||
|
while (*s) {
|
||||||
|
if (((*s) < '0') || ((*s) > '9')) return 0;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#define FOUND_OTHER ( (void *)-1)
|
#define FOUND_OTHER ( (void *)-1)
|
||||||
#define FILE_NOT_FOUND ((void *)-2)
|
#define FILE_NOT_FOUND ((void *)-2)
|
||||||
/* will return a token array containing [host,]ip keytype key */
|
/* will return a token array containing [host,]ip keytype key */
|
||||||
@@ -741,6 +752,7 @@ static char **ssh_parse_knownhost(char *filename, char *hostname, char *type){
|
|||||||
FILE *file=fopen(filename,"r");
|
FILE *file=fopen(filename,"r");
|
||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
char *found_type;
|
||||||
char **tokens;
|
char **tokens;
|
||||||
char **ret=NULL;
|
char **ret=NULL;
|
||||||
if(!file)
|
if(!file)
|
||||||
@@ -753,16 +765,29 @@ static char **ssh_parse_knownhost(char *filename, char *hostname, char *type){
|
|||||||
continue; /* skip empty lines */
|
continue; /* skip empty lines */
|
||||||
tokens=space_tokenize(buffer);
|
tokens=space_tokenize(buffer);
|
||||||
if(!tokens[0] || !tokens[1] || !tokens[2]){
|
if(!tokens[0] || !tokens[1] || !tokens[2]){
|
||||||
/* it should have exactly 3 tokens */
|
/* it should have at least 3 tokens */
|
||||||
free(tokens[0]);
|
free(tokens[0]);
|
||||||
free(tokens);
|
free(tokens);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
found_type = tokens[1];
|
||||||
if(tokens[3]){
|
if(tokens[3]){
|
||||||
/* 3 tokens only, not four */
|
/* openssh rsa1 format has 4 tokens on the line. Recognize it
|
||||||
free(tokens[0]);
|
by the fact that everything is all digits */
|
||||||
free(tokens);
|
if (tokens[4]) {
|
||||||
continue;
|
/* that's never valid */
|
||||||
|
free(tokens[0]);
|
||||||
|
free(tokens);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (alldigits(tokens[1]) && alldigits(tokens[2]) && alldigits(tokens[3])) {
|
||||||
|
found_type = "ssh-rsa1";
|
||||||
|
} else {
|
||||||
|
/* 3 tokens only, not four */
|
||||||
|
free(tokens[0]);
|
||||||
|
free(tokens);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ptr=tokens[0];
|
ptr=tokens[0];
|
||||||
while(*ptr==' ')
|
while(*ptr==' ')
|
||||||
@@ -772,7 +797,7 @@ static char **ssh_parse_knownhost(char *filename, char *hostname, char *type){
|
|||||||
if(strncasecmp(ptr,hostname,strlen(hostname))==0){
|
if(strncasecmp(ptr,hostname,strlen(hostname))==0){
|
||||||
if(ptr[strlen(hostname)]==' ' || ptr[strlen(hostname)]=='\0'
|
if(ptr[strlen(hostname)]==' ' || ptr[strlen(hostname)]=='\0'
|
||||||
|| ptr[strlen(hostname)]==','){
|
|| ptr[strlen(hostname)]==','){
|
||||||
if(strcasecmp(tokens[1],type)==0){
|
if(strcasecmp(found_type, type)==0){
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return tokens;
|
return tokens;
|
||||||
} else {
|
} else {
|
||||||
@@ -814,8 +839,39 @@ int ssh_is_server_known(SSH_SESSION *session){
|
|||||||
/* Some time, we may verify the IP address did not change. I honestly think */
|
/* Some time, we may verify the IP address did not change. I honestly think */
|
||||||
/* it's not an important matter as IP address are known not to be secure */
|
/* it's not an important matter as IP address are known not to be secure */
|
||||||
/* and the crypto stuff is enough to prove the server's identity */
|
/* and the crypto stuff is enough to prove the server's identity */
|
||||||
pubkey_64=tokens[2];
|
if (alldigits(tokens[1])) { /* openssh rsa1 format */
|
||||||
pubkey_buffer=base64_to_bin(pubkey_64);
|
bignum tmpbn;
|
||||||
|
int i;
|
||||||
|
unsigned int len;
|
||||||
|
STRING *tmpstring;
|
||||||
|
|
||||||
|
pubkey_buffer = buffer_new();
|
||||||
|
tmpstring = string_from_char("ssh-rsa1");
|
||||||
|
buffer_add_ssh_string(pubkey_buffer, tmpstring);
|
||||||
|
|
||||||
|
for (i = 2; i < 4; i++) { /* e, then n */
|
||||||
|
tmpbn = NULL;
|
||||||
|
bignum_dec2bn(tokens[i], &tmpbn);
|
||||||
|
/* for some reason, make_bignum_string does not work
|
||||||
|
because of the padding which it does --kv */
|
||||||
|
/* tmpstring = make_bignum_string(tmpbn); */
|
||||||
|
/* do it manually instead */
|
||||||
|
len = bignum_num_bytes(tmpbn);
|
||||||
|
tmpstring = malloc(4 + len);
|
||||||
|
tmpstring->size = htonl(len);
|
||||||
|
#ifdef HAVE_LIBGCRYPT
|
||||||
|
bignum_bn2bin(tmpbn, len, tmpstring->string);
|
||||||
|
#elif defined HAVE_LIBCRYPTO
|
||||||
|
bignum_bn2bin(tmpbn, tmpstring->string);
|
||||||
|
#endif
|
||||||
|
bignum_free(tmpbn);
|
||||||
|
buffer_add_ssh_string(pubkey_buffer, tmpstring);
|
||||||
|
free(tmpstring);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pubkey_64=tokens[2];
|
||||||
|
pubkey_buffer=base64_to_bin(pubkey_64);
|
||||||
|
}
|
||||||
/* at this point, we may free the tokens */
|
/* at this point, we may free the tokens */
|
||||||
free(tokens[0]);
|
free(tokens[0]);
|
||||||
free(tokens);
|
free(tokens);
|
||||||
@@ -853,9 +909,47 @@ int ssh_write_knownhost(SSH_SESSION *session){
|
|||||||
session->options->known_hosts_file,strerror(errno));
|
session->options->known_hosts_file,strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
pubkey_64=bin_to_base64(pubkey->string,string_len(pubkey));
|
if (!strcmp(session->current_crypto->server_pubkey_type, "ssh-rsa1")) {
|
||||||
snprintf(buffer,sizeof(buffer),"%s %s %s\n",session->options->host,session->current_crypto->server_pubkey_type,pubkey_64);
|
/* openssh uses a different format for ssh-rsa1 keys.
|
||||||
free(pubkey_64);
|
Be compatible --kv */
|
||||||
|
char *e_string, *n_string;
|
||||||
|
bignum e, n;
|
||||||
|
PUBLIC_KEY *key = publickey_from_string(pubkey);
|
||||||
|
int rsa_size;
|
||||||
|
#ifdef HAVE_LIBGCRYPT
|
||||||
|
gcry_sexp_t sexp;
|
||||||
|
sexp=gcry_sexp_find_token(key->rsa_pub,"e",0);
|
||||||
|
e=gcry_sexp_nth_mpi(sexp,1,GCRYMPI_FMT_USG);
|
||||||
|
gcry_sexp_release(sexp);
|
||||||
|
sexp=gcry_sexp_find_token(key->rsa_pub,"n",0);
|
||||||
|
n=gcry_sexp_nth_mpi(sexp,1,GCRYMPI_FMT_USG);
|
||||||
|
gcry_sexp_release(sexp);
|
||||||
|
rsa_size=(gcry_pk_get_nbits(key->rsa_pub)+7)/8;
|
||||||
|
#elif defined HAVE_LIBCRYPTO
|
||||||
|
e = key->rsa_pub->e;
|
||||||
|
n = key->rsa_pub->n;
|
||||||
|
rsa_size = RSA_size(key->rsa_pub);
|
||||||
|
#endif
|
||||||
|
e_string = bignum_bn2dec(e);
|
||||||
|
n_string = bignum_bn2dec(n);
|
||||||
|
snprintf(buffer, sizeof(buffer), "%s %d %s %s\n",
|
||||||
|
session->options->host, rsa_size << 3,
|
||||||
|
e_string, n_string);
|
||||||
|
#ifdef HAVE_LIBGCRYPT
|
||||||
|
free(e_string);
|
||||||
|
gcry_mpi_release(e);
|
||||||
|
free(n_string);
|
||||||
|
gcry_mpi_release(n);
|
||||||
|
#elif defined HAVE_LIBCRYPTO
|
||||||
|
OPENSSL_free(e_string);
|
||||||
|
OPENSSL_free(n_string);
|
||||||
|
#endif
|
||||||
|
free(key);
|
||||||
|
} else {
|
||||||
|
pubkey_64=bin_to_base64(pubkey->string,string_len(pubkey));
|
||||||
|
snprintf(buffer,sizeof(buffer),"%s %s %s\n",session->options->host,session->current_crypto->server_pubkey_type,pubkey_64);
|
||||||
|
free(pubkey_64);
|
||||||
|
}
|
||||||
fwrite(buffer,strlen(buffer),1,file);
|
fwrite(buffer,strlen(buffer),1,file);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user