1
0
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:
Jean-Philippe Garcia Ballester
2005-11-25 09:31:33 +00:00
parent d923851664
commit ac4fd09177
5 changed files with 207 additions and 17 deletions

View File

@@ -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

View File

@@ -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
View 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

View File

@@ -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) )

View File

@@ -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;