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_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_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_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)
|
||||
@@ -108,6 +110,8 @@ typedef BN_CTX* bignum_CTX;
|
||||
#define bignum_free(num) BN_clear_free(num)
|
||||
#define bignum_set_word(bn,n) BN_set_word(bn,n)
|
||||
#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_rand(rnd, bits, top, bottom) BN_rand(rnd,bits,top,bottom)
|
||||
#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);
|
||||
|
||||
#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
|
||||
} ;
|
||||
#endif
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
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 messages.o channels1.o auth1.o sftpserver.o
|
||||
session.o messages.o channels1.o auth1.o sftpserver.o \
|
||||
gcrypt_missing.o
|
||||
SHELL = /bin/sh
|
||||
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){
|
||||
bignum n1;
|
||||
bignum n2;
|
||||
int res;
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
gcry_sexp_t sexp;
|
||||
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);
|
||||
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);
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
n1=k1->rsa_pub->n;
|
||||
n2=k2->rsa_pub->n;
|
||||
#endif
|
||||
if(bignum_cmp(n1,n2)<0)
|
||||
return 1;
|
||||
res=1;
|
||||
else
|
||||
return 0;
|
||||
res=0;
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
bignum_free(n1);
|
||||
bignum_free(n2);
|
||||
#endif
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
#define ABS(A) ( (A)<0 ? -(A):(A) )
|
||||
|
||||
@@ -29,7 +29,9 @@ MA 02111-1307, USA. */
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include "libssh/priv.h"
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
#include <gcrypt.h>
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/err.h>
|
||||
@@ -732,6 +734,15 @@ STRING *publickey_from_next_file(SSH_SESSION *session,char **pub_keys_path,char
|
||||
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 FILE_NOT_FOUND ((void *)-2)
|
||||
/* 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");
|
||||
char buffer[4096];
|
||||
char *ptr;
|
||||
char *found_type;
|
||||
char **tokens;
|
||||
char **ret=NULL;
|
||||
if(!file)
|
||||
@@ -753,17 +765,30 @@ static char **ssh_parse_knownhost(char *filename, char *hostname, char *type){
|
||||
continue; /* skip empty lines */
|
||||
tokens=space_tokenize(buffer);
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
found_type = tokens[1];
|
||||
if(tokens[3]){
|
||||
/* openssh rsa1 format has 4 tokens on the line. Recognize it
|
||||
by the fact that everything is all digits */
|
||||
if (tokens[4]) {
|
||||
/* 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];
|
||||
while(*ptr==' ')
|
||||
ptr++; /* skip the initial spaces */
|
||||
@@ -772,7 +797,7 @@ static char **ssh_parse_knownhost(char *filename, char *hostname, char *type){
|
||||
if(strncasecmp(ptr,hostname,strlen(hostname))==0){
|
||||
if(ptr[strlen(hostname)]==' ' || ptr[strlen(hostname)]=='\0'
|
||||
|| ptr[strlen(hostname)]==','){
|
||||
if(strcasecmp(tokens[1],type)==0){
|
||||
if(strcasecmp(found_type, type)==0){
|
||||
fclose(file);
|
||||
return tokens;
|
||||
} 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 */
|
||||
/* 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 */
|
||||
if (alldigits(tokens[1])) { /* openssh rsa1 format */
|
||||
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 */
|
||||
free(tokens[0]);
|
||||
free(tokens);
|
||||
@@ -853,9 +909,47 @@ int ssh_write_knownhost(SSH_SESSION *session){
|
||||
session->options->known_hosts_file,strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (!strcmp(session->current_crypto->server_pubkey_type, "ssh-rsa1")) {
|
||||
/* openssh uses a different format for ssh-rsa1 keys.
|
||||
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);
|
||||
fclose(file);
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user