diff options
author | Jean-Philippe Garcia Ballester <giga@le-pec.org> | 2005-11-25 09:31:33 +0000 |
---|---|---|
committer | Jean-Philippe Garcia Ballester <giga@le-pec.org> | 2005-11-25 09:31:33 +0000 |
commit | ac4fd091775805b6849774f3c4b7e59dc1ab6bde (patch) | |
tree | 0e2b654829aa923b68fecbe67e056a71a71e3f07 /libssh | |
parent | d923851664f20f7143981dde3562ae9d6ce0b72e (diff) | |
download | libssh-ac4fd091775805b6849774f3c4b7e59dc1ab6bde.tar.gz libssh-ac4fd091775805b6849774f3c4b7e59dc1ab6bde.tar.xz libssh-ac4fd091775805b6849774f3c4b7e59dc1ab6bde.zip |
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
Diffstat (limited to 'libssh')
-rw-r--r-- | libssh/Makefile.in | 3 | ||||
-rw-r--r-- | libssh/gcrypt_missing.c | 78 | ||||
-rw-r--r-- | libssh/kex.c | 15 | ||||
-rw-r--r-- | libssh/keyfiles.c | 118 |
4 files changed, 197 insertions, 17 deletions
diff --git a/libssh/Makefile.in b/libssh/Makefile.in index 963fa21..5b28caa 100644 --- a/libssh/Makefile.in +++ b/libssh/Makefile.in @@ -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@ diff --git a/libssh/gcrypt_missing.c b/libssh/gcrypt_missing.c new file mode 100644 index 0000000..10f9da8 --- /dev/null +++ b/libssh/gcrypt_missing.c @@ -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 diff --git a/libssh/kex.c b/libssh/kex.c index 5097b06..1d66f28 100644 --- a/libssh/kex.c +++ b/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) ) diff --git a/libssh/keyfiles.c b/libssh/keyfiles.c index e299295..ee0b3ec 100644 --- a/libssh/keyfiles.c +++ b/libssh/keyfiles.c @@ -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,16 +765,29 @@ 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]){ - /* 3 tokens only, not four */ - free(tokens[0]); - free(tokens); - continue; + /* 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==' ') @@ -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 */ - pubkey_64=tokens[2]; - pubkey_buffer=base64_to_bin(pubkey_64); + 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; } - 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); + 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; |