aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.h.in9
-rwxr-xr-xconfigure15
-rw-r--r--configure.in15
-rw-r--r--include/libssh/crypto.h15
-rw-r--r--include/libssh/libssh.h11
-rw-r--r--include/libssh/priv.h105
-rw-r--r--libssh/auth.c2
-rw-r--r--libssh/auth1.c3
-rw-r--r--libssh/base64.c6
-rw-r--r--libssh/buffer.c2
-rw-r--r--libssh/channels.c30
-rw-r--r--libssh/client.c7
-rw-r--r--libssh/connect.c64
-rw-r--r--libssh/crypt.c28
-rw-r--r--libssh/dh.c169
-rw-r--r--libssh/gzip.c1
-rw-r--r--libssh/kex.c13
-rw-r--r--libssh/keyfiles.c484
-rw-r--r--libssh/keys.c313
-rw-r--r--libssh/messages.c1
-rw-r--r--libssh/packet.c6
-rw-r--r--libssh/server.c2
-rw-r--r--libssh/session.c1
-rw-r--r--libssh/sftp.c1
-rw-r--r--libssh/sftpserver.c1
-rw-r--r--libssh/string.c2
-rw-r--r--libssh/wrapper.c218
-rw-r--r--sample.c2
-rw-r--r--samplesshd.c1
29 files changed, 1339 insertions, 188 deletions
diff --git a/config.h.in b/config.h.in
index 6abb2cb4..58d95c45 100644
--- a/config.h.in
+++ b/config.h.in
@@ -12,6 +12,9 @@
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
+/* Define to 1 if you have the <gcrypt.h> header file. */
+#undef HAVE_GCRYPT_H
+
/* Define to 1 if you have the `gethostbyaddr' function. */
#undef HAVE_GETHOSTBYADDR
@@ -27,6 +30,9 @@
/* Define to 1 if you have the `crypto' library (-lcrypto). */
#undef HAVE_LIBCRYPTO
+/* Define to 1 if you have the `gcrypt' library (-lgcrypt). */
+#undef HAVE_LIBGCRYPT
+
/* Define to 1 if you have the `z' library (-lz). */
#undef HAVE_LIBZ
@@ -55,6 +61,9 @@
/* Define to 1 if you have the <openssl/blowfish.h> header file. */
#undef HAVE_OPENSSL_BLOWFISH_H
+/* Define to 1 if you have the <openssl/des.h> header file. */
+#undef HAVE_OPENSSL_DES_H
+
/* Define to 1 if you have the <pam/pam_appl.h> header file. */
#undef HAVE_PAM_PAM_APPL_H
diff --git a/configure b/configure
index 5df9f8c0..cf03f7a8 100755
--- a/configure
+++ b/configure
@@ -2786,6 +2786,10 @@ esac
# Checks for libraries.
+# AC_CHECK_LIB([gcrypt], [gcry_md_open])
+# if test "$ac_cv_lib_gcrypt_gcry_md_open" != yes; then
+# AC_CHECK_LIB([crypto], [BN_init])
+# fi
echo "$as_me:$LINENO: checking for BN_init in -lcrypto" >&5
echo $ECHO_N "checking for BN_init in -lcrypto... $ECHO_C" >&6
@@ -3693,9 +3697,12 @@ done
+
+
for ac_header in fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h \
-sys/time.h termios.h unistd.h openssl/aes.h openssl/blowfish.h zlib.h \
-sys/poll.h stdint.h pty.h pam/pam_appl.h security/pam_appl.h
+sys/time.h termios.h unistd.h openssl/aes.h openssl/blowfish.h \
+openssl/des.h zlib.h sys/poll.h stdint.h pty.h pam/pam_appl.h \
+security/pam_appl.h gcrypt.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -5089,8 +5096,8 @@ done
-for ac_func in endpwent gethostbyaddr gethostbyname getpass memmove memset cfmakeraw\
- select socket strchr strdup strerror strstr poll
+for ac_func in endpwent gethostbyaddr gethostbyname getpass memmove memset \
+cfmakeraw select socket strchr strdup strerror strstr poll
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
echo "$as_me:$LINENO: checking for $ac_func" >&5
diff --git a/configure.in b/configure.in
index 65f356a7..2f7a7db0 100644
--- a/configure.in
+++ b/configure.in
@@ -38,7 +38,11 @@ AC_PROG_RANLIB
AC_C_BIGENDIAN
# Checks for libraries.
-AC_CHECK_LIB([crypto], [BN_init])
+# AC_CHECK_LIB([gcrypt], [gcry_md_open])
+# if test "$ac_cv_lib_gcrypt_gcry_md_open" != yes; then
+# AC_CHECK_LIB([crypto], [BN_init])
+# fi
+AC_CHECK_LIB([crypto],[BN_init])
AC_CHECK_LIB([z], [deflateInit_])
AC_SEARCH_LIBS([hstrerror],[nsl resolv])
AC_SEARCH_LIBS([gethostbyname],[nsl resolv])
@@ -46,8 +50,9 @@ AC_SEARCH_LIBS([gethostbyname],[nsl resolv])
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h \
-sys/time.h termios.h unistd.h openssl/aes.h openssl/blowfish.h zlib.h \
-sys/poll.h stdint.h pty.h pam/pam_appl.h security/pam_appl.h])
+sys/time.h termios.h unistd.h openssl/aes.h openssl/blowfish.h \
+openssl/des.h zlib.h sys/poll.h stdint.h pty.h pam/pam_appl.h \
+security/pam_appl.h gcrypt.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
@@ -60,8 +65,8 @@ AC_FUNC_REALLOC
AC_FUNC_SELECT_ARGTYPES
AC_TYPE_SIGNAL
AC_FUNC_VPRINTF
-AC_CHECK_FUNCS([endpwent gethostbyaddr gethostbyname getpass memmove memset cfmakeraw\
- select socket strchr strdup strerror strstr poll])
+AC_CHECK_FUNCS([endpwent gethostbyaddr gethostbyname getpass memmove memset \
+cfmakeraw select socket strchr strdup strerror strstr poll])
AC_CONFIG_FILES([Makefile
libssh/Makefile
diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h
index 3b8426cc..0714f3d4 100644
--- a/include/libssh/crypto.h
+++ b/include/libssh/crypto.h
@@ -33,15 +33,30 @@ MA 02111-1307, USA. */
#ifdef des_set_key
#undef des_set_key
#endif
+#ifdef GCRYPT
+#include <gcrypt.h>
+#endif
+
struct crypto_struct {
char *name; /* ssh name of the algorithm */
unsigned int blocksize; /* blocksize of the algo */
unsigned int keylen; /* length of the key structure */
+#ifdef HAVE_LIBGCRYPT
+ gcry_cipher_hd_t *key;
+#elif defined HAVE_LIBCRYPTO
void *key; /* a key buffer allocated for the algo */
+#endif
unsigned int keysize; /* bytes of key used. != keylen */
+#ifdef HAVE_LIBGCRYPT
+ void (*set_encrypt_key)(struct crypto_struct *cipher, void *key, void *IV); /* sets the new key for immediate use */
+ void (*set_decrypt_key)(struct crypto_struct *cipher, void *key, void *IV);
+ void (*cbc_encrypt)(struct crypto_struct *cipher, void *in, void *out,unsigned long len);
+ void (*cbc_decrypt)(struct crypto_struct *cipher, void *in, void *out,unsigned long len);
+#elif defined HAVE_LIBCRYPTO
void (*set_encrypt_key)(struct crypto_struct *cipher, void *key); /* sets the new key for immediate use */
void (*set_decrypt_key)(struct crypto_struct *cipher, void *key);
void (*cbc_encrypt)(struct crypto_struct *cipher, void *in, void *out,unsigned long len,void *IV);
void (*cbc_decrypt)(struct crypto_struct *cipher, void *in, void *out,unsigned long len,void *IV);
+#endif
};
diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h
index ac843e0d..f49b3f5c 100644
--- a/include/libssh/libssh.h
+++ b/include/libssh/libssh.h
@@ -20,13 +20,12 @@ MA 02111-1307, USA. */
#ifndef _LIBSSH_H
#define _LIBSSH_H
-#include <libssh/config.h>
#include <unistd.h>
#include <sys/select.h> /* for fd_set * */
#include <sys/types.h>
-#ifdef HAVE_STDINT_H
+
#include <stdint.h>
-#endif
+
#define LIBSSH_VERSION "libssh-0.2-dev"
#ifdef __cplusplus
@@ -126,7 +125,7 @@ const char *ssh_copyright();
STRING *string_from_char(char *what);
/* it returns the string len in host byte orders. str->size is big endian warning ! */
int string_len(STRING *str);
-STRING *string_new(u32 size);
+STRING *string_new(unsigned int size);
/* string_fill copies the data in the string. it does NOT check for boundary so allocate enough place with string_new */
void string_fill(STRING *str,void *data,int len);
/* returns a newly allocated char array with the str string and a final nul caracter */
@@ -144,11 +143,11 @@ void ssh_print_hexa(char *descr,unsigned char *what, int len);
int ssh_get_random(void *where,int len,int strong);
/* this one can be called by the client to see the hash of the public key before accepting it */
-int ssh_get_pubkey_hash(SSH_SESSION *session,char hash[MD5_DIGEST_LEN]);
+int ssh_get_pubkey_hash(SSH_SESSION *session,unsigned char hash[MD5_DIGEST_LEN]);
STRING *ssh_get_pubkey(SSH_SESSION *session);
/* in connect.c */
-int ssh_fd_poll(SSH_SESSION *session);
+int ssh_fd_poll(SSH_SESSION *session,int *write, int *except);
int ssh_select(CHANNEL **channels,CHANNEL **outchannels, int maxfd, fd_set *readfds, struct timeval *timeout);
void publickey_free(PUBLIC_KEY *key);
diff --git a/include/libssh/priv.h b/include/libssh/priv.h
index c6a4b48d..aab8c300 100644
--- a/include/libssh/priv.h
+++ b/include/libssh/priv.h
@@ -25,6 +25,7 @@ MA 02111-1307, USA. */
#ifndef _LIBSSH_PRIV_H
#define _LIBSSH_PRIV_H
+#include "config.h"
#include "libssh/libssh.h"
/* Debugging constants */
@@ -45,25 +46,51 @@ MA 02111-1307, USA. */
#define TYPE_RSA1 3
/* profiling constants. Don't touch them unless you know what you do */
-#define OPENSSL_CRYPTO
+#ifdef HAVE_LIBCRYPTO
#define OPENSSL_BIGNUMS
-
+#endif
#ifdef __cplusplus
extern "C" {
#endif
/* wrapper things */
-
-#ifdef OPENSSL_CRYPTO
+#ifdef HAVE_LIBGCRYPT
+#include <gcrypt.h>
+typedef gcry_md_hd_t SHACTX;
+typedef gcry_md_hd_t MD5CTX;
+typedef gcry_md_hd_t HMACCTX;
+#ifdef MD5_DIGEST_LEN
+ #undef MD5_DIGEST_LEN
+#endif
+#define SHA_DIGEST_LEN 20
+#define MD5_DIGEST_LEN 16
+#define EVP_MAX_MD_SIZE 36
+
+typedef gcry_mpi_t bignum;
+
+#define bignum_new() gcry_mpi_new(0)
+#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_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)
+#define bignum_mod_exp(dest,generator,exp,modulo) gcry_mpi_powm(dest,generator,exp,modulo)
+#define bignum_num_bits(num) gcry_mpi_get_nbits(num)
+#define bignum_num_bytes(num) ((gcry_mpi_get_nbits(num)+7)/8)
+#define bignum_is_bit_set(num,bit) gcry_mpi_test_bit(num,bit)
+#define bignum_bn2bin(num,datalen,data) gcry_mpi_print(GCRYMPI_FMT_USG,data,datalen,NULL,num)
+
+#elif defined HAVE_LIBCRYPTO
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <openssl/md5.h>
#include <openssl/hmac.h>
-typedef SHA_CTX SHACTX;
-typedef MD5_CTX MD5CTX;
-typedef HMAC_CTX HMACCTX;
+typedef SHA_CTX* SHACTX;
+typedef MD5_CTX* MD5CTX;
+typedef HMAC_CTX* HMACCTX;
#ifdef MD5_DIGEST_LEN
#undef MD5_DIGEST_LEN
#endif
@@ -91,29 +118,30 @@ typedef BN_CTX* bignum_CTX;
#define bignum_bn2bin(num,ptr) BN_bn2bin(num,ptr)
#endif /* OPENSSL_BIGNUMS */
+
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
/* wrapper.c */
-MD5CTX *md5_init(void);
-void md5_update(MD5CTX *c, const void *data, unsigned long len);
-void md5_final(unsigned char *md,MD5CTX *c);
-SHACTX *sha1_init(void);
-void sha1_update(SHACTX *c, const void *data, unsigned long len);
-void sha1_final(unsigned char *md,SHACTX *c);
+MD5CTX md5_init(void);
+void md5_update(MD5CTX c, const void *data, unsigned long len);
+void md5_final(unsigned char *md,MD5CTX c);
+SHACTX sha1_init(void);
+void sha1_update(SHACTX c, const void *data, unsigned long len);
+void sha1_final(unsigned char *md,SHACTX c);
void sha1(unsigned char *digest,int len,unsigned char *hash);
#define HMAC_SHA1 1
#define HMAC_MD5 2
-HMACCTX *hmac_init(const void *key,int len,int type);
-void hmac_update(HMACCTX *c, const void *data, unsigned long len);
-void hmac_final(HMACCTX *ctx,unsigned char *hashmacbuf,int *len);
+HMACCTX hmac_init(const void *key,int len,int type);
+void hmac_update(HMACCTX c, const void *data, unsigned long len);
+void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len);
/* strings and buffers */
/* must be 32 bits number + immediatly our data */
struct string_struct {
u32 size;
- char string[MAX_PACKET_LEN];
+ unsigned char string[MAX_PACKET_LEN];
} __attribute__ ((packed));
@@ -132,27 +160,42 @@ typedef struct packet_struct {
} PACKET;
typedef struct kex_struct {
- char cookie[16];
+ unsigned char cookie[16];
char **methods;
} KEX;
struct public_key_struct {
int type;
char *type_c; /* Don't free it ! it is static */
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_t dsa_pub;
+ gcry_sexp_t rsa_pub;
+#elif HAVE_LIBCRYPTO
DSA *dsa_pub;
RSA *rsa_pub;
+#endif
};
struct private_key_struct {
int type;
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_t dsa_priv;
+ gcry_sexp_t rsa_priv;
+#elif defined HAVE_LIBCRYPTO
DSA *dsa_priv;
RSA *rsa_priv;
+#endif
};
typedef struct signature_struct {
int type;
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_t dsa_sign;
+ gcry_sexp_t rsa_sign;
+#elif defined HAVE_LIBCRYPTO
DSA_SIG *dsa_sign;
STRING *rsa_sign;
+#endif
} SIGNATURE;
struct ssh_options_struct {
@@ -183,17 +226,17 @@ struct ssh_options_struct {
typedef struct ssh_crypto_struct {
bignum e,f,x,k,y;
- char session_id[SHA_DIGEST_LEN];
+ unsigned char session_id[SHA_DIGEST_LEN];
- char encryptIV[SHA_DIGEST_LEN*2];
- char decryptIV[SHA_DIGEST_LEN*2];
+ unsigned char encryptIV[SHA_DIGEST_LEN*2];
+ unsigned char decryptIV[SHA_DIGEST_LEN*2];
- char decryptkey[SHA_DIGEST_LEN*2];
- char encryptkey[SHA_DIGEST_LEN*2];
+ unsigned char decryptkey[SHA_DIGEST_LEN*2];
+ unsigned char encryptkey[SHA_DIGEST_LEN*2];
- char encryptMAC[SHA_DIGEST_LEN];
- char decryptMAC[SHA_DIGEST_LEN];
- char hmacbuf[EVP_MAX_MD_SIZE];
+ unsigned char encryptMAC[SHA_DIGEST_LEN];
+ unsigned char decryptMAC[SHA_DIGEST_LEN];
+ unsigned char hmacbuf[EVP_MAX_MD_SIZE];
struct crypto_struct *in_cipher, *out_cipher; /* the cipher structures/objects */
STRING *server_pubkey;
char *server_pubkey_type;
@@ -302,7 +345,7 @@ struct ssh_kbdint {
char *name;
char *instruction;
char **prompts;
- char *echo; /* bool array */
+ unsigned char *echo; /* bool array */
char **answers;
};
/* session.c */
@@ -320,6 +363,7 @@ void ssh_set_error(void *error,int code,char *descr,...);
/* in dh.c */
/* DH key generation */
void dh_generate_e(SSH_SESSION *session);
+void ssh_print_bignum(char *which,bignum num);
void dh_generate_x(SSH_SESSION *session);
void dh_generate_y(SSH_SESSION *session);
void dh_generate_f(SSH_SESSION *session);
@@ -343,9 +387,9 @@ STRING *make_bignum_string(bignum num);
/* in crypt.c */
u32 packet_decrypt_len(SSH_SESSION *session,char *crypted);
int packet_decrypt(SSH_SESSION *session, void *packet,unsigned int len);
-char *packet_encrypt(SSH_SESSION *session,void *packet,unsigned int len);
+unsigned char *packet_encrypt(SSH_SESSION *session,void *packet,unsigned int len);
/* it returns the hmac buffer if exists*/
-int packet_hmac_verify(SSH_SESSION *session,BUFFER *buffer,char *mac);
+int packet_hmac_verify(SSH_SESSION *session,BUFFER *buffer,unsigned char *mac);
/* in packet.c */
void packet_clear_out(SSH_SESSION *session);
@@ -434,7 +478,7 @@ int buffer_pass_bytes(BUFFER *buffer, int len);
/* in base64.c */
BUFFER *base64_to_bin(char *source);
-char *bin_to_base64(unsigned char *source, int len);
+unsigned char *bin_to_base64(unsigned char *source, int len);
/* gzip.c */
int compress_buffer(SSH_SESSION *session,BUFFER *buf);
@@ -445,7 +489,6 @@ int crypt_set_algorithms(SSH_SESSION *);
int crypt_set_algorithms_server(SSH_SESSION *session);
CRYPTO *crypto_new();
void crypto_free(CRYPTO *crypto);
-bignum bignum_new();
/* crc32.c */
u32 ssh_crc32(char *buffer, int len);
diff --git a/libssh/auth.c b/libssh/auth.c
index 938dff6b..12b90bf4 100644
--- a/libssh/auth.c
+++ b/libssh/auth.c
@@ -21,6 +21,8 @@ MA 02111-1307, USA. */
#include "libssh/priv.h"
#include "libssh/ssh2.h"
+#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
#include <netdb.h>
diff --git a/libssh/auth1.c b/libssh/auth1.c
index 65fc9058..40cccda1 100644
--- a/libssh/auth1.c
+++ b/libssh/auth1.c
@@ -23,6 +23,7 @@ MA 02111-1307, USA. */
#include "libssh/ssh1.h"
#include <string.h>
#include <netdb.h>
+#include <stdlib.h>
/*
static void burn(char *ptr){
@@ -187,7 +188,7 @@ int ssh_userauth1_password(SSH_SESSION *session,char *username,char *password){
*/
password_s=string_new(128);
ssh_get_random(password_s->string,128,0);
- strcpy(password_s->string,password);
+ strcpy((char *)password_s->string,password);
}
packet_clear_out(session);
diff --git a/libssh/base64.c b/libssh/base64.c
index 1f0b415d..f16be600 100644
--- a/libssh/base64.c
+++ b/libssh/base64.c
@@ -193,10 +193,10 @@ static void _bin_to_base64(unsigned char *dest, unsigned char source[3], int len
}
}
-char *bin_to_base64(unsigned char *source, int len){
+unsigned char *bin_to_base64(unsigned char *source, int len){
int flen=len + (3 - (len %3)); /* round to upper 3 multiple */
- char *buffer;
- char *ptr;
+ unsigned char *buffer;
+ unsigned char *ptr;
flen=(4 * flen)/3 + 1 ;
ptr=buffer=malloc(flen);
while(len>0){
diff --git a/libssh/buffer.c b/libssh/buffer.c
index b511a8cd..9cdf8599 100644
--- a/libssh/buffer.c
+++ b/libssh/buffer.c
@@ -150,7 +150,7 @@ STRING *buffer_get_ssh_string(BUFFER *buffer){
hostlen=ntohl(stringlen);
/* verify if there is enough space in buffer to get it */
if(buffer->pos+hostlen>buffer->used)
- return 0; /* it is indeed */
+ return NULL; /* it is indeed */
str=string_new(hostlen);
if(buffer_get_data(buffer,str->string,hostlen)!=hostlen){
ssh_say(0,"buffer_get_ssh_string: oddish : second test failed when first was successful. len=%d",hostlen);
diff --git a/libssh/channels.c b/libssh/channels.c
index 31586314..8a0b1fa1 100644
--- a/libssh/channels.c
+++ b/libssh/channels.c
@@ -661,18 +661,20 @@ int channel_read(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr){
/* returns the number of bytes available, 0 if nothing is currently available, -1 if error */
int channel_poll(CHANNEL *channel, int is_stderr){
BUFFER *buffer;
+ int r=0,w=0,err=0;
if(is_stderr)
buffer=channel->stderr_buffer;
else
buffer=channel->stdout_buffer;
while(buffer_get_rest_len(buffer)==0 && !channel->remote_eof){
- if(ssh_fd_poll(channel->session)){
- if(packet_read(channel->session)||packet_translate(channel->session))
- return -1;
- packet_parse(channel->session);
- } else
- return 0; /* nothing is available has said fd_poll */
+ r=ssh_fd_poll(channel->session,&w,&err);
+ if(r<=0)
+ return r; // error or no data available
+ /* if an exception happened, it will be trapped by packet_read() */
+ if(packet_read(channel->session)||packet_translate(channel->session))
+ return -1;
+ packet_parse(channel->session);
}
if(channel->remote_eof)
return 1;
@@ -700,4 +702,18 @@ int channel_read_nonblocking(CHANNEL *channel, char *dest, int len, int is_stder
SSH_SESSION *channel_get_session(CHANNEL *channel){
return channel->session;
}
-
+/*
+int channel_select(CHANNEL *readchans, CHANNEL *writechans, CHANNEL *exceptchans, struct
+ timeval * timeout){
+ fd_set rset;
+ fd_set wset;
+ fd_set eset;
+ int rmax=-1, wmax=-1, emax=-1; // nothing to do with the low quality editor :)
+ int i;
+ FD_ZERO(rset);
+ FD_ZERO(wset);
+ FD_ZERO(eset);
+ for(i=0;readchans[i];++i){
+ if(!readchans[i].
+
+*/ \ No newline at end of file
diff --git a/libssh/client.c b/libssh/client.c
index 42b10414..1ca8952d 100644
--- a/libssh/client.c
+++ b/libssh/client.c
@@ -26,6 +26,7 @@ MA 02111-1307, USA. */
#include <netdb.h>
#include "libssh/priv.h"
#include "libssh/ssh2.h"
+extern int connections;
#define set_status(opt,status) do {\
if (opt->connect_status_function) \
@@ -277,6 +278,12 @@ void ssh_disconnect(SSH_SESSION *session){
}
session->alive=0;
ssh_cleanup(session);
+ if (!--connections)
+#ifdef HAVE_LIBGCRYPT
+ gcry_control(GCRYCTL_TERM_SECMEM);
+#elif defined HAVE_LIBCRYPTO
+ EVP_cleanup();
+#endif
}
const char *ssh_copyright(){
diff --git a/libssh/connect.c b/libssh/connect.c
index ccb704ff..d1e8bf59 100644
--- a/libssh/connect.c
+++ b/libssh/connect.c
@@ -32,15 +32,16 @@ MA 02111-1307, USA. */
#include <netinet/in.h>
#include <fcntl.h>
#include "libssh/priv.h"
-#ifdef HAVE_SYS_POLL_H
-#include <sys/poll.h>
-#endif
#ifndef HAVE_GETHOSTBYNAME
#ifndef HAVE_GETHOSTBYADDR
#error "your system doesn't have gethostbyname nor gethostbyaddr"
#endif
#endif
+#ifndef HAVE_SELECT
+#error "Your system must have select()"
+#endif
+
static void sock_set_nonblocking(int sock) {
fcntl(sock,F_SETFL,O_NONBLOCK);
}
@@ -118,7 +119,7 @@ int ssh_connect_host(SSH_SESSION *session, const char *host, const char
struct timeval to;
fd_set set;
int ret=0;
- int len=sizeof(ret);
+ unsigned int len=sizeof(ret);
to.tv_sec=timeout;
to.tv_usec=usec;
sock_set_nonblocking(s);
@@ -157,46 +158,45 @@ int ssh_connect_host(SSH_SESSION *session, const char *host, const char
return s;
}
-/* returns 1 if bytes are available on the stream, 0 instead */
-int ssh_fd_poll(SSH_SESSION *session){
-#ifdef HAVE_POLL
- struct pollfd fdset;
-#else
+/* returns 1 if bytes are available to read on the stream, 0 instead */
+/* -1 on select() error. */
+int ssh_fd_poll(SSH_SESSION *session, int *write, int *except){
struct timeval sometime;
- fd_set descriptor;
-#endif
- if(session->data_to_read)
- return(session->data_to_read);
-#ifdef HAVE_POLL
- fdset.fd=session->fd;
- fdset.events=POLLHUP|POLLIN|POLLPRI;
- fdset.revents=0;
- if(poll(&fdset,1,0)==0)
+ fd_set rdes; // read set
+ fd_set wdes; // writing set
+ fd_set edes; // exception set
+
+ FD_ZERO(&rdes);
+ FD_ZERO(&wdes);
+ FD_ZERO(&edes);
+
+ if(!session->alive){
+ *except=1;
+ *write=0;
return 0;
- if(fdset.revents & (POLLHUP|POLLIN|POLLPRI))
- return (session->data_to_read=1);
- return 0;
-#elif HAVE_SELECT
+ }
+ if(!session->data_to_read)
+ FD_SET(session->fd,&rdes);
+ if(!session->data_to_write)
+ FD_SET(session->fd,&wdes);
+ FD_SET(session->fd,&edes);
/* Set to return immediately (no blocking) */
sometime.tv_sec = 0;
sometime.tv_usec = 0;
- /* Set up descriptor */
- FD_ZERO(&descriptor);
- FD_SET(session->fd, &descriptor);
-
/* Make the call, and listen for errors */
- if (select(session->fd + 1, &descriptor, NULL, NULL, &sometime) < 0) {
+ if (select(session->fd + 1, &rdes,&wdes,&edes, &sometime) < 0) {
ssh_set_error(NULL,SSH_FATAL, "select: %s", strerror(errno));
return -1;
}
- session->data_to_read=FD_ISSET(session->fd,&descriptor);
+ if(!session->data_to_read)
+ session->data_to_read=FD_ISSET(session->fd,&rdes);
+ if(!session->data_to_write)
+ session->data_to_write=FD_ISSET(session->fd,&wdes);
+ *except=FD_ISSET(session->fd,&edes);
+ *write=session->data_to_write;
return session->data_to_read;
-#else
-#error This system does not have poll() or select(), so ssh_fd_poll() will not work correctly
- return 0;
-#endif
}
/* this function is a complete wrapper for the select syscall. it does more than wrapping ... */
diff --git a/libssh/crypt.c b/libssh/crypt.c
index 5daab609..e118f6a7 100644
--- a/libssh/crypt.c
+++ b/libssh/crypt.c
@@ -22,11 +22,14 @@ MA 02111-1307, USA. */
#include <unistd.h>
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
+#ifdef OPENSSL_CRYPTO
#include <openssl/blowfish.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
+#endif
#include <netdb.h>
#include "libssh/priv.h"
@@ -45,25 +48,34 @@ int packet_decrypt(SSH_SESSION *session, void *data,u32 len){
struct crypto_struct *crypto=session->current_crypto->in_cipher;
char *out=malloc(len);
ssh_say(3,"Decrypting %d bytes data\n",len);
+#ifdef HAVE_LIBGCRYPT
+ crypto->set_decrypt_key(crypto,session->current_crypto->decryptkey,session->current_crypto->decryptIV);
+ crypto->cbc_decrypt(crypto,data,out,len);
+#elif defined HAVE_LIBCRYPTO
crypto->set_decrypt_key(crypto,session->current_crypto->decryptkey);
crypto->cbc_decrypt(crypto,data,out,len,session->current_crypto->decryptIV);
+#endif
memcpy(data,out,len);
memset(out,0,len);
free(out);
return 0;
}
-char * packet_encrypt(SSH_SESSION *session,void *data,u32 len){
+unsigned char * packet_encrypt(SSH_SESSION *session,void *data,u32 len){
struct crypto_struct *crypto;
- HMAC_CTX *ctx;
+ HMACCTX ctx;
char *out;
- int finallen;
+ unsigned int finallen;
u32 seq=ntohl(session->send_seq);
if(!session->current_crypto)
return NULL; /* nothing to do here */
crypto= session->current_crypto->out_cipher;
ssh_say(3,"seq num = %d, len = %d\n",session->send_seq,len);
+#ifdef HAVE_LIBGCRYPT
+ crypto->set_encrypt_key(crypto,session->current_crypto->encryptkey,session->current_crypto->encryptIV);
+#elif defined HAVE_LIBCRYPTO
crypto->set_encrypt_key(crypto,session->current_crypto->encryptkey);
+#endif
out=malloc(len);
if(session->version==2){
ctx=hmac_init(session->current_crypto->encryptMAC,20,HMAC_SHA1);
@@ -77,7 +89,11 @@ char * packet_encrypt(SSH_SESSION *session,void *data,u32 len){
ssh_print_hexa("packet hmac",session->current_crypto->hmacbuf,20);
#endif
}
+#ifdef HAVE_LIBGCRYPT
+ crypto->cbc_encrypt(crypto,data,out,len);
+#elif defined HAVE_LIBCRYPTO
crypto->cbc_encrypt(crypto,data,out,len,session->current_crypto->encryptIV);
+#endif
memcpy(data,out,len);
memset(out,0,len);
free(out);
@@ -87,10 +103,10 @@ char * packet_encrypt(SSH_SESSION *session,void *data,u32 len){
return NULL;
}
-int packet_hmac_verify(SSH_SESSION *session,BUFFER *buffer,char *mac){
- HMAC_CTX *ctx;
+int packet_hmac_verify(SSH_SESSION *session,BUFFER *buffer,unsigned char *mac){
+ HMACCTX ctx;
unsigned char hmacbuf[EVP_MAX_MD_SIZE];
- int len;
+ unsigned int len;
u32 seq=htonl(session->recv_seq);
ctx=hmac_init(session->current_crypto->decryptMAC,20,HMAC_SHA1);
hmac_update(ctx,(unsigned char *)&seq,sizeof(u32));
diff --git a/libssh/dh.c b/libssh/dh.c
index c96c70ac..89fda259 100644
--- a/libssh/dh.c
+++ b/libssh/dh.c
@@ -42,9 +42,11 @@ MA 02111-1307, USA. */
#include <netdb.h>
#include "libssh/priv.h"
+#ifdef HAVE_LIBCRYPTO
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/err.h>
+#endif
#include <string.h>
#include "libssh/crypto.h"
static unsigned char p_value[] = {
@@ -65,13 +67,23 @@ static unsigned long g_int = 2 ; /* G is defined as 2 by the ssh2 standards */
static bignum g;
static bignum p;
+int connections = 0;
+
/* maybe it might be enhanced .... */
/* XXX Do it. */
int ssh_get_random(void *where, int len, int strong){
if(strong){
+#ifdef HAVE_LIBGCRYPT
+ gcry_randomize(where,len,GCRY_VERY_STRONG_RANDOM);
+ return 1;
+ } else {
+ gcry_randomize(where,len,GCRY_STRONG_RANDOM);
+ return 1;
+#elif defined HAVE_LIBCRYPTO
return RAND_bytes(where,len);
} else {
return RAND_pseudo_bytes(where,len);
+#endif
}
}
@@ -79,19 +91,39 @@ int ssh_get_random(void *where, int len, int strong){
void ssh_crypto_init(){
static int init=0;
if(!init){
+#ifdef HAVE_LIBGCRYPT
+ gcry_check_version(NULL);
+#endif
g=bignum_new();
bignum_set_word(g,g_int);
+#ifdef HAVE_LIBGCRYPT
+ bignum_bin2bn(p_value,P_LEN,&p);
+#elif defined HAVE_LIBCRYPTO
p=bignum_new();
bignum_bin2bn(p_value,P_LEN,p);
+#endif
init++;
}
+ if (!connections++){
+#ifdef HAVE_LIBGCRYPT
+ gcry_control(GCRYCTL_INIT_SECMEM,524288,0);
+ gcry_control(GCRYCTL_INITIALIZATION_FINISHED,0);
+#elif defined HAVE_LIBCRYPTO
+ OpenSSL_add_all_algorithms();
+#endif
+ }
}
/* prints the bignum on stderr */
void ssh_print_bignum(char *which,bignum num){
+#ifdef HAVE_LIBGCRYPT
+ unsigned char *hex;
+ bignum_bn2hex(num,&hex);
+#elif defined HAVE_LIBCRYPTO
char *hex;
- fprintf(stderr,"%s value: ",which);
hex=bignum_bn2hex(num);
+#endif
+ fprintf(stderr,"%s value: ",which);
fprintf(stderr,"%s\n",hex);
free(hex);
}
@@ -111,7 +143,11 @@ void ssh_print_hexa(char *descr,unsigned char *what, int len){
void dh_generate_x(SSH_SESSION *session){
session->next_crypto->x=bignum_new();
+#ifdef HAVE_LIBGCRYPT
+ bignum_rand(session->next_crypto->x,128);
+#elif defined HAVE_LIBCRYPTO
bignum_rand(session->next_crypto->x,128,0,-1);
+#endif
/* not harder than this */
#ifdef DEBUG_CRYPTO
ssh_print_bignum("x",session->next_crypto->x);
@@ -120,7 +156,11 @@ void dh_generate_x(SSH_SESSION *session){
/* used by server */
void dh_generate_y(SSH_SESSION *session){
session->next_crypto->y=bignum_new();
+#ifdef HAVE_LIBGCRYPT
+ bignum_rand(session->next_crypto->y,128);
+#elif defined HAVE_LIBCRYPTO
bignum_rand(session->next_crypto->y,128,0,-1);
+#endif
/* not harder than this */
#ifdef DEBUG_CRYPTO
ssh_print_bignum("y",session->next_crypto->y);
@@ -128,31 +168,46 @@ void dh_generate_y(SSH_SESSION *session){
}
/* used by server */
void dh_generate_e(SSH_SESSION *session){
+#ifdef HAVE_LIBCRYPTO
bignum_CTX ctx=bignum_ctx_new();
+#endif
session->next_crypto->e=bignum_new();
+#ifdef HAVE_LIBGCRYPT
+ bignum_mod_exp(session->next_crypto->e,g,session->next_crypto->x,p);
+#elif defined HAVE_LIBCRYPTO
bignum_mod_exp(session->next_crypto->e,g,session->next_crypto->x,p,ctx);
+#endif
#ifdef DEBUG_CRYPTO
ssh_print_bignum("e",session->next_crypto->e);
#endif
+#ifdef HAVE_LIBCRYPTO
bignum_ctx_free(ctx);
+#endif
}
void dh_generate_f(SSH_SESSION *session){
+#ifdef HAVE_LIBCRYPTO
bignum_CTX ctx=bignum_ctx_new();
+#endif
session->next_crypto->f=bignum_new();
+#ifdef HAVE_LIBGCRYPT
+ bignum_mod_exp(session->next_crypto->f,g,session->next_crypto->y,p);
+#elif defined HAVE_LIBCRYPTO
bignum_mod_exp(session->next_crypto->f,g,session->next_crypto->y,p,ctx);
+#endif
#ifdef DEBUG_CRYPTO
ssh_print_bignum("f",session->next_crypto->f);
#endif
+#ifdef HAVE_LIBCRYPTO
bignum_ctx_free(ctx);
+#endif
}
STRING *make_bignum_string(bignum num){
STRING *ptr;
int pad=0;
- int len=bignum_num_bytes(num);
- int bits=bignum_num_bits(num);
- int finallen;
+ unsigned int len=bignum_num_bytes(num);
+ unsigned int bits=bignum_num_bits(num);
/* remember if the fist bit is set, it is considered as a negative number. so 0's must be appended */
if(!(bits%8) && bignum_is_bit_set(num,bits-1))
pad++;
@@ -161,14 +216,24 @@ STRING *make_bignum_string(bignum num){
ptr->size=htonl(len+pad);
if(pad)
ptr->string[0]=0;
- finallen=bignum_bn2bin(num,ptr->string+pad);
+#ifdef HAVE_LIBGCRYPT
+ bignum_bn2bin(num,len,ptr->string+pad);
+#elif HAVE_LIBCRYPTO
+ bignum_bn2bin(num,ptr->string+pad);
+#endif
return ptr;
}
bignum make_string_bn(STRING *string){
- int len=ntohl(string->size);
+ bignum bn;
+ unsigned int len=string_len(string);
ssh_say(3,"Importing a %d bits,%d bytes object ...\n",len*8,len);
- return bignum_bin2bn(string->string,len,NULL);
+#ifdef HAVE_LIBGCRYPT
+ bignum_bin2bn(string->string,len,&bn);
+#elif defined HAVE_LIBCRYPTO
+ bn=bignum_bin2bn(string->string,len,NULL);
+#endif
+ return bn;
}
STRING *dh_get_e(SSH_SESSION *session){
@@ -200,21 +265,33 @@ void dh_import_e(SSH_SESSION *session, STRING *e_string){
}
void dh_build_k(SSH_SESSION *session){
+#ifdef HAVE_LIBCRYPTO
bignum_CTX ctx=bignum_ctx_new();
+#endif
session->next_crypto->k=bignum_new();
/* the server and clients don't use the same numbers */
+#ifdef HAVE_LIBGCRYPT
+ if(session->client){
+ bignum_mod_exp(session->next_crypto->k,session->next_crypto->f,session->next_crypto->x,p);
+ } else {
+ bignum_mod_exp(session->next_crypto->k,session->next_crypto->e,session->next_crypto->y,p);
+ }
+#elif defined HAVE_LIBCRYPTO
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);
}
+#endif
#ifdef DEBUG_CRYPTO
ssh_print_bignum("shared secret key",session->next_crypto->k);
#endif
+#ifdef HAVE_LIBCRYPTO
bignum_ctx_free(ctx);
+#endif
}
/*
-static void sha_add(STRING *str,SHACTX *ctx){
+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);
@@ -222,7 +299,7 @@ static void sha_add(STRING *str,SHACTX *ctx){
}
*/
void make_sessionid(SSH_SESSION *session){
- SHACTX *ctx;
+ SHACTX ctx;
STRING *num,*str;
BUFFER *server_hash, *client_hash;
BUFFER *buf=buffer_new();
@@ -294,7 +371,7 @@ void make_sessionid(SSH_SESSION *session){
buffer_free(buf);
#ifdef DEBUG_CRYPTO
printf("Session hash : ");
- ssh_print_hexa("session id",session->next_crypto->session_id,SHA_DIGEST_LENGTH);
+ ssh_print_hexa("session id",session->next_crypto->session_id,SHA_DIGEST_LEN);
#endif
}
@@ -314,18 +391,18 @@ void hashbufin_add_cookie(SSH_SESSION *session,unsigned char *cookie){
buffer_add_data(session->in_hashbuf,cookie,16);
}
-static void generate_one_key(STRING *k,char session_id[SHA_DIGEST_LENGTH],char output[SHA_DIGEST_LENGTH],char letter){
- SHACTX *ctx=sha1_init();
+static void generate_one_key(STRING *k,unsigned char session_id[SHA_DIGEST_LEN],unsigned char output[SHA_DIGEST_LEN],char letter){
+ SHACTX ctx=sha1_init();
sha1_update(ctx,k,string_len(k)+4);
- sha1_update(ctx,session_id,SHA_DIGEST_LENGTH);
+ sha1_update(ctx,session_id,SHA_DIGEST_LEN);
sha1_update(ctx,&letter,1);
- sha1_update(ctx,session_id,SHA_DIGEST_LENGTH);
+ sha1_update(ctx,session_id,SHA_DIGEST_LEN);
sha1_final(output,ctx);
}
void generate_session_keys(SSH_SESSION *session){
STRING *k_string;
- SHACTX *ctx;
+ SHACTX ctx;
k_string=make_bignum_string(session->next_crypto->k);
/* IV */
@@ -345,19 +422,19 @@ void generate_session_keys(SSH_SESSION *session){
}
/* 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){
+ if(session->next_crypto->out_cipher->keysize > SHA_DIGEST_LEN*8){
ctx=sha1_init();
sha1_update(ctx,k_string,string_len(k_string)+4);
- sha1_update(ctx,session->next_crypto->session_id,SHA_DIGEST_LENGTH);
- sha1_update(ctx,session->next_crypto->encryptkey,SHA_DIGEST_LENGTH);
+ sha1_update(ctx,session->next_crypto->session_id,SHA_DIGEST_LEN);
+ sha1_update(ctx,session->next_crypto->encryptkey,SHA_DIGEST_LEN);
sha1_final(session->next_crypto->encryptkey+SHA_DIGEST_LEN,ctx);
}
- if(session->next_crypto->in_cipher->keylen > SHA_DIGEST_LENGTH*8){
+ if(session->next_crypto->in_cipher->keysize > SHA_DIGEST_LEN*8){
ctx=sha1_init();
sha1_update(ctx,k_string,string_len(k_string)+4);
- sha1_update(ctx,session->next_crypto->session_id,SHA_DIGEST_LENGTH);
- sha1_update(ctx,session->next_crypto->decryptkey,SHA_DIGEST_LENGTH);
+ sha1_update(ctx,session->next_crypto->session_id,SHA_DIGEST_LEN);
+ sha1_update(ctx,session->next_crypto->decryptkey,SHA_DIGEST_LEN);
sha1_final(session->next_crypto->decryptkey+SHA_DIGEST_LEN,ctx);
}
if(session->client){
@@ -369,19 +446,19 @@ void generate_session_keys(SSH_SESSION *session){
}
#ifdef DEBUG_CRYPTO
- 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("encrypt IV",session->next_crypto->encryptIV,SHA_DIGEST_LEN);
+ ssh_print_hexa("decrypt IV",session->next_crypto->decryptIV,SHA_DIGEST_LEN);
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);
+ ssh_print_hexa("Encryption MAC",session->next_crypto->encryptMAC,SHA_DIGEST_LEN);
ssh_print_hexa("Decryption MAC",session->next_crypto->decryptMAC,20);
#endif
free(k_string);
}
-int ssh_get_pubkey_hash(SSH_SESSION *session,char hash[MD5_DIGEST_LEN]){
+int ssh_get_pubkey_hash(SSH_SESSION *session,unsigned char hash[MD5_DIGEST_LEN]){
STRING *pubkey=session->current_crypto->server_pubkey;
- MD5CTX *ctx;
+ MD5CTX ctx;
int len=string_len(pubkey);
ctx=md5_init();
@@ -390,7 +467,7 @@ int ssh_get_pubkey_hash(SSH_SESSION *session,char hash[MD5_DIGEST_LEN]){
return MD5_DIGEST_LEN;
}
-int pubkey_get_hash(SSH_SESSION *session, char hash[MD5_DIGEST_LEN]){
+int pubkey_get_hash(SSH_SESSION *session, unsigned char hash[MD5_DIGEST_LEN]){
return ssh_get_pubkey_hash(session,hash);
}
@@ -424,33 +501,59 @@ static int match(char *group,char *object){
}
static int sig_verify(SSH_SESSION *session, PUBLIC_KEY *pubkey, SIGNATURE *signature,
- char *digest){
+ unsigned char *digest){
+#ifdef HAVE_LIBGCRYPT
+ gcry_error_t valid=0;
+ gcry_sexp_t gcryhash;
+#elif defined HAVE_LIBCRYPTO
int valid=0;
- char hash[SHA_DIGEST_LENGTH];
- sha1(digest,SHA_DIGEST_LENGTH,hash);
+#endif
+ unsigned char hash[SHA_DIGEST_LEN+1];
+ sha1(digest,SHA_DIGEST_LEN,hash+1);
+ hash[0]=0;
#ifdef DEBUG_CRYPTO
- ssh_print_hexa("hash to be verified with dsa",hash,SHA_DIGEST_LENGTH);
+ ssh_print_hexa("hash to be verified with dsa",hash+1,SHA_DIGEST_LEN);
#endif
switch(pubkey->type){
case TYPE_DSS:
- valid=DSA_do_verify(hash,SHA_DIGEST_LENGTH,signature->dsa_sign,
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_build(&gcryhash, NULL, "%b", SHA_DIGEST_LEN+1, hash);
+ valid=gcry_pk_verify(signature->dsa_sign,gcryhash,pubkey->dsa_pub);
+ gcry_sexp_release(gcryhash);
+ if(valid==0)
+ return 0;
+ if (gcry_err_code(valid)!=GPG_ERR_BAD_SIGNATURE){
+ ssh_set_error(NULL,SSH_FATAL,"DSA error : %s", gcry_strerror(valid));
+#elif defined HAVE_LIBCRYPTO
+ valid=DSA_do_verify(hash+1,SHA_DIGEST_LEN,signature->dsa_sign,
pubkey->dsa_pub);
if(valid==1)
return 0;
if(valid==-1){
ssh_set_error(session,SSH_FATAL,"DSA error : %s",ERR_error_string(ERR_get_error(),NULL));
+#endif
return -1;
}
ssh_set_error(session,SSH_FATAL,"Invalid DSA signature");
return -1;
case TYPE_RSA:
case TYPE_RSA1:
- valid=RSA_verify(NID_sha1,hash,SHA_DIGEST_LENGTH,
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_build(&gcryhash,NULL,"(data(flags pkcs1)(hash sha1 %b))",SHA_DIGEST_LEN,hash+1);
+ valid=gcry_pk_verify(signature->rsa_sign,gcryhash,pubkey->rsa_pub);
+ gcry_sexp_release(gcryhash);
+ if(valid==0)
+ return 0;
+ if(gcry_err_code(valid)!=GPG_ERR_BAD_SIGNATURE){
+ ssh_set_error(NULL,SSH_FATAL,"RSA error : %s",gcry_strerror(valid));
+#elif defined HAVE_LIBCRYPTO
+ valid=RSA_verify(NID_sha1,hash+1,SHA_DIGEST_LEN,
signature->rsa_sign->string,string_len(signature->rsa_sign),pubkey->rsa_pub);
if(valid==1)
return 0;
if(valid==-1){
ssh_set_error(session,SSH_FATAL,"RSA error : %s",ERR_error_string(ERR_get_error(),NULL));
+#endif
return -1;
}
ssh_set_error(session,SSH_FATAL,"Invalid RSA signature");
diff --git a/libssh/gzip.c b/libssh/gzip.c
index 0b04f905..0af45f1f 100644
--- a/libssh/gzip.c
+++ b/libssh/gzip.c
@@ -29,6 +29,7 @@ MA 02111-1307, USA. */
#ifndef NO_GZIP
#include <zlib.h>
#include <string.h>
+#include <stdlib.h>
#define BLOCKSIZE 4092
static z_stream *initcompress(SSH_SESSION *session,int level){
diff --git a/libssh/kex.c b/libssh/kex.c
index 7b7722e0..e069bf79 100644
--- a/libssh/kex.c
+++ b/libssh/kex.c
@@ -26,6 +26,11 @@ MA 02111-1307, USA. */
#include "libssh/ssh2.h"
#include "libssh/ssh1.h"
+#ifdef HAVE_LIBGCRYPT
+#define BLOWFISH "blowfish-cbc,"
+#define AES "aes256-cbc,aes192-cbc,aes128-cbc,"
+#define DES "3des-cbc"
+#elif defined HAVE_LIBCRYPTO
#ifdef HAVE_OPENSSL_BLOWFISH_H
#define BLOWFISH "blowfish-cbc,"
#else
@@ -36,13 +41,15 @@ MA 02111-1307, USA. */
#else
#define AES ""
#endif
-
#define DES "3des-cbc"
+#endif
+
#ifdef HAVE_LIBZ
#define ZLIB "none,zlib"
#else
#define ZLIB "none"
#endif
+
char *default_methods[]={
"diffie-hellman-group1-sha1","ssh-dss,ssh-rsa",AES BLOWFISH DES,AES BLOWFISH
DES, "hmac-sha1","hmac-sha1","none","none","","",NULL };
@@ -286,7 +293,7 @@ static STRING *make_rsa1_string(STRING *e, STRING *n){
static void build_session_id1(SSH_SESSION *session, STRING *servern,
STRING *hostn){
- MD5CTX *md5=md5_init();
+ MD5CTX md5=md5_init();
#ifdef DEBUG_CRYPTO
ssh_print_hexa("host modulus",hostn->string,string_len(hostn));
ssh_print_hexa("server modulus",servern->string,string_len(servern));
@@ -313,7 +320,7 @@ static int modulus_smaller(PUBLIC_KEY *k1, PUBLIC_KEY *k2){
#define ABS(A) ( (A)<0 ? -(A):(A) )
STRING *encrypt_session_key(SSH_SESSION *session, PUBLIC_KEY *svrkey,
PUBLIC_KEY *hostkey,int slen, int hlen ){
- char buffer[32];
+ unsigned char buffer[32];
int i;
STRING *data1,*data2;
/* first, generate a session key */
diff --git a/libssh/keyfiles.c b/libssh/keyfiles.c
index 93223538..e2992952 100644
--- a/libssh/keyfiles.c
+++ b/libssh/keyfiles.c
@@ -28,12 +28,431 @@ MA 02111-1307, USA. */
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
+#include "libssh/priv.h"
+#ifdef HAVE_LIBCRYPTO
#include <openssl/pem.h>
#include <openssl/dsa.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
-#include "libssh/priv.h"
+#endif
+#include <netinet/in.h>
#define MAXLINESIZE 80
+#ifdef HAVE_LIBGCRYPT
+#define MAX_KEY_SIZE 32
+#define MAX_PASSPHRASE_SIZE 1024
+#define RSA_HEADER_BEGIN "-----BEGIN RSA PRIVATE KEY-----"
+#define RSA_HEADER_END "-----END RSA PRIVATE KEY-----"
+#define DSA_HEADER_BEGIN "-----BEGIN DSA PRIVATE KEY-----"
+#define DSA_HEADER_END "-----END DSA PRIVATE KEY-----"
+#define ASN1_INTEGER 2
+#define ASN1_SEQUENCE 48
+#define PKCS5_SALT_LEN 8
+
+int load_iv(char *header, unsigned char *iv, int iv_len)
+{
+ int i;
+ int j;
+ int k;
+
+ memset(iv, 0, iv_len);
+ for (i=0; i < iv_len; i++)
+ {
+ if ((header[2*i] >= '0') && (header[2*i] <= '9'))
+ j = header[2*i] - '0';
+ else if ((header[2*i] >= 'A') && (header[2*i] <= 'F'))
+ j = header[2*i] - 'A' + 10;
+ else if ((header[2*i] >= 'a') && (header[2*i] <= 'f'))
+ j = header[2*i] - 'a' + 10;
+ else
+ return 0;
+ if ((header[2*i+1] >= '0') && (header[2*i+1] <= '9'))
+ k = header[2*i+1] - '0';
+ else if ((header[2*i+1] >= 'A') && (header[2*i+1] <= 'F'))
+ k = header[2*i+1] - 'A' + 10;
+ else if ((header[2*i+1] >= 'a') && (header[2*i+1] <= 'f'))
+ k = header[2*i+1] - 'a' + 10;
+ else
+ return 0;
+ iv[i] = (j << 4) + k;
+ }
+ return 1;
+}
+
+u32 char_to_u32(unsigned char *data, u32 size)
+{
+ u32 ret;
+ u32 i;
+
+ for (i=0,ret=0;i<size;ret=ret<<8,ret+=data[i++])
+ ;
+ return ret;
+}
+
+u32 asn1_get_len(BUFFER *buffer)
+{
+ u32 len;
+ unsigned char tmp[4];
+
+ if (!buffer_get_data(buffer,tmp,1))
+ return 0;
+ if (tmp[0] > 127)
+ {
+ len=tmp[0] & 127;
+ if (len>4)
+ return 0; /* Length doesn't fit in u32. Can this really happen? */
+ if (!buffer_get_data(buffer,tmp,len))
+ return 0;
+ len=char_to_u32(tmp,len);
+ }
+ else
+ len=char_to_u32(tmp,1);
+ return len;
+}
+
+STRING *asn1_get_int(BUFFER *buffer)
+{
+ STRING *ret;
+ unsigned char type;
+ u32 size;
+
+ if (!buffer_get_data(buffer,&type,1) || type != ASN1_INTEGER)
+ return NULL;
+ size=asn1_get_len(buffer);
+ if (!size)
+ return NULL;
+ ret=string_new(size);
+ if (!buffer_get_data(buffer,ret->string,size))
+ return NULL;
+ return ret;
+}
+
+int asn1_check_sequence(BUFFER *buffer)
+{
+ unsigned char tmp;
+ unsigned char *j;
+ int i;
+ u32 size;
+
+ if (!buffer_get_data(buffer,&tmp,1) || tmp != ASN1_SEQUENCE)
+ return 0;
+ size=asn1_get_len(buffer);
+ if (size != buffer_get_len(buffer) - buffer->pos)
+ for (i = buffer_get_len(buffer) - buffer->pos - size,
+ j = buffer_get(buffer) + size + buffer->pos; i; i--, j++)
+ {
+ if (*j != 1) /* padding is allowed */
+ return 0; /* but nothing else */
+ }
+ return 1;
+}
+
+int read_line(char *data, unsigned int len, FILE *fp)
+{
+ char tmp;
+ int i;
+
+ for (i=0; fread(&tmp, 1, 1, fp) && tmp!='\n' && i<len; data[i++]=tmp)
+ ;
+ if (tmp=='\n')
+ return i;
+ if (i>=len)
+ return -1;
+ return 0;
+}
+
+int passphrase_to_key(char *data, unsigned int datalen, unsigned char *salt, unsigned char *key,unsigned int keylen)
+{
+ MD5CTX md;
+ unsigned char digest[MD5_DIGEST_LEN];
+ unsigned int i;
+ unsigned int j;
+ unsigned int md_not_empty;
+
+ for (j=0,md_not_empty=0;j<keylen;)
+ {
+ md = md5_init();
+ if (!md)
+ return 0;
+ if (md_not_empty)
+ md5_update(md,digest,MD5_DIGEST_LEN);
+ else
+ md_not_empty=1;
+ md5_update(md,data,datalen);
+ if (salt)
+ md5_update(md, salt, PKCS5_SALT_LEN);
+ md5_final(digest,md);
+ for (i = 0; j < keylen && i < MD5_DIGEST_LEN; j++, i++)
+ if (key)
+ key[j] = digest[i];
+ }
+ return 1;
+}
+
+int privatekey_decrypt(int algo, int mode, unsigned int key_len,
+ unsigned char *iv, unsigned int iv_len,
+ BUFFER *data, int cb(char *,int , int , char *),
+ char *desc)
+{
+ gcry_cipher_hd_t cipher;
+ unsigned int passphrase_len;
+ char passphrase[MAX_PASSPHRASE_SIZE];
+ unsigned char key[MAX_KEY_SIZE];
+ unsigned char *tmp;
+ gcry_error_t err;
+
+ if (!algo)
+ return 1;
+ passphrase_len=cb(passphrase, MAX_PASSPHRASE_SIZE, 0, desc);
+ if (passphrase_len <= 0)
+ return 0;
+ passphrase_to_key(passphrase, passphrase_len, iv, key, key_len);
+ if (gcry_cipher_open(&cipher, algo, mode, GCRY_CIPHER_SECURE)
+ || gcry_cipher_setkey(cipher, key, key_len)
+ || gcry_cipher_setiv(cipher, iv, iv_len)
+ || !(tmp = malloc(buffer_get_len(data) * sizeof (char)))
+ || (err = gcry_cipher_decrypt(cipher, tmp, buffer_get_len(data),
+ buffer_get(data), buffer_get_len(data))))
+ {
+ gcry_cipher_close(cipher);
+ return 0;
+ }
+ memcpy(buffer_get(data), tmp, buffer_get_len(data));
+ gcry_cipher_close(cipher);
+ return 1;
+}
+
+int privatekey_dek_header(char *header, unsigned int header_len, int *algo, int *mode, unsigned int *key_len, unsigned char **iv, unsigned int *iv_len)
+{
+ unsigned int iv_pos;
+
+ if (header_len > 13 && !strncmp("DES-EDE3-CBC", header, 12))
+ {
+ *algo = GCRY_CIPHER_3DES;
+ iv_pos = 13;
+ *mode = GCRY_CIPHER_MODE_CBC;
+ *key_len = 24;
+ *iv_len = 8;
+ }
+ else if (header_len > 8 && !strncmp("DES-CBC", header, 7))
+ {
+ *algo = GCRY_CIPHER_DES;
+ iv_pos = 8;
+ *mode = GCRY_CIPHER_MODE_CBC;
+ *key_len = 8;
+ *iv_len = 8;
+ }
+ else if (header_len > 12 && !strncmp("AES-128-CBC", header, 11))
+ {
+ *algo = GCRY_CIPHER_AES128;
+ iv_pos = 12;
+ *mode = GCRY_CIPHER_MODE_CBC;
+ *key_len = 16;
+ *iv_len = 16;
+ }
+ else if (header_len > 12 && !strncmp("AES-192-CBC", header, 11))
+ {
+ *algo = GCRY_CIPHER_AES192;
+ iv_pos = 12;
+ *mode = GCRY_CIPHER_MODE_CBC;
+ *key_len = 24;
+ *iv_len = 16;
+ }
+ else if (header_len > 12 && !strncmp("AES-256-CBC", header, 11))
+ {
+ *algo = GCRY_CIPHER_AES256;
+ iv_pos = 12;
+ *mode = GCRY_CIPHER_MODE_CBC;
+ *key_len = 32;
+ *iv_len = 16;
+ }
+ else
+ return 0;
+ *iv = malloc(*iv_len);
+ load_iv(header + iv_pos, *iv, *iv_len);
+ return 1;
+}
+
+BUFFER *privatekey_file_to_buffer(FILE *fp, int type, int cb(char *, int , int , char *), char *desc)
+{
+ char buf[MAXLINESIZE];
+ char *header_begin;
+ unsigned int header_begin_size;
+ char *header_end;
+ unsigned int header_end_size;
+ BUFFER *buffer=buffer_new();
+ BUFFER *ret;
+ int len;
+ int algo = 0;
+ int mode = 0;
+ unsigned int key_len = 0;
+ unsigned char *iv = NULL;
+ unsigned int iv_len = 0;
+
+ switch(type)
+ {
+ case TYPE_DSS:
+ header_begin=DSA_HEADER_BEGIN;
+ header_end=DSA_HEADER_END;
+ break;
+ case TYPE_RSA:
+ header_begin=RSA_HEADER_BEGIN;
+ header_end=RSA_HEADER_END;
+ break;
+ default:
+ return NULL;
+ }
+ header_begin_size=strlen(header_begin);
+ header_end_size=strlen(header_end);
+ while (read_line(buf,MAXLINESIZE,fp) && strncmp(buf,header_begin,header_begin_size))
+ ;
+ len = read_line(buf, MAXLINESIZE, fp);
+ if (len > 11 && !strncmp("Proc-Type: 4,ENCRYPTED", buf, 11))
+ {
+ len = read_line(buf, MAXLINESIZE, fp);
+ if (len > 10 && !strncmp("DEK-Info: ", buf, 10))
+ {
+ if (!privatekey_dek_header(buf + 10, len - 10, &algo, &mode, &key_len,
+ &iv, &iv_len)
+ || read_line(buf, MAXLINESIZE, fp))
+ {
+ buffer_free(buffer);
+ free(iv);
+ return NULL;
+ }
+ }
+ else
+ {
+ buffer_free(buffer);
+ free(iv);
+ return NULL;
+ }
+ }
+ else
+ buffer_add_data(buffer,buf,len);
+ while ((len = read_line(buf,MAXLINESIZE,fp))
+ && strncmp(buf,header_end,header_end_size))
+ {
+ if (len == -1)
+ {
+ buffer_free(buffer);
+ free(iv);
+ return NULL;
+ }
+ buffer_add_data(buffer,buf,len);
+ }
+ if (strncmp(buf,header_end,header_end_size))
+ {
+ buffer_free(buffer);
+ free(iv);
+ return NULL;
+ }
+ buffer_add_data(buffer,"\0",1);
+ ret=base64_to_bin(buffer_get(buffer));
+ buffer_free(buffer);
+ if (algo)
+ {
+ if (!privatekey_decrypt(algo, mode, key_len, iv, iv_len, ret, cb, desc))
+ {
+ free(iv);
+ return NULL;
+ }
+ }
+ free(iv);
+ return ret;
+}
+
+int read_rsa_privatekey(FILE *fp, gcry_sexp_t *r,
+ int cb(char *, int , int , char *), char *desc)
+{
+ STRING *n;
+ STRING *e;
+ STRING *d;
+ STRING *p;
+ STRING *q;
+ STRING *unused1;
+ STRING *unused2;
+ STRING *u;
+ STRING *v;
+ BUFFER *buffer;
+
+ if (!(buffer=privatekey_file_to_buffer(fp, TYPE_RSA, cb, desc)))
+ return 0;
+ if (!asn1_check_sequence(buffer))
+ {
+ buffer_free(buffer);
+ return 0;
+ }
+ v=asn1_get_int(buffer);
+ if (ntohl(v->size)!=1 || v->string[0]!=0)
+ {
+ buffer_free(buffer);
+ return 0;
+ }
+ n=asn1_get_int(buffer);
+ e=asn1_get_int(buffer);
+ d=asn1_get_int(buffer);
+ q=asn1_get_int(buffer);
+ p=asn1_get_int(buffer);
+ unused1=asn1_get_int(buffer);
+ unused2=asn1_get_int(buffer);
+ u=asn1_get_int(buffer);
+ buffer_free(buffer);
+ if (!n || !e || !d || !p || !q || !unused1 || !unused2 || !u)
+ return 0;
+ gcry_sexp_build(r,NULL,"(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))",ntohl(n->size),n->string,ntohl(e->size),e->string,ntohl(d->size),d->string,ntohl(p->size),p->string,ntohl(q->size),q->string,ntohl(u->size),u->string);
+ free(n);
+ free(e);
+ free(d);
+ free(p);
+ free(q);
+ free(unused1);
+ free(unused2);
+ free(u);
+ free(v);
+ return 1;
+}
+
+int read_dsa_privatekey(FILE *fp, gcry_sexp_t *r, int cb(char *, int , int , char *), char *desc)
+{
+ STRING *p;
+ STRING *q;
+ STRING *g;
+ STRING *y;
+ STRING *x;
+ STRING *v;
+ BUFFER *buffer;
+
+ if (!(buffer=privatekey_file_to_buffer(fp, TYPE_DSS, cb, desc)))
+ return 0;
+ if (!asn1_check_sequence(buffer))
+ {
+ buffer_free(buffer);
+ return 0;
+ }
+ v=asn1_get_int(buffer);
+ if (ntohl(v->size)!=1 || v->string[0]!=0)
+ {
+ buffer_free(buffer);
+ return 0;
+ }
+ p=asn1_get_int(buffer);
+ q=asn1_get_int(buffer);
+ g=asn1_get_int(buffer);
+ y=asn1_get_int(buffer);
+ x=asn1_get_int(buffer);
+ buffer_free(buffer);
+ if (!p || !q || !g || !y || !x)
+ return 0;
+ gcry_sexp_build(r,NULL,"(private-key(dsa(p %b)(q %b)(g %b)(y %b)(x %b)))",ntohl(p->size),p->string,ntohl(q->size),q->string,ntohl(g->size),g->string,ntohl(y->size),y->string,ntohl(x->size),x->string);
+ free(p);
+ free(q);
+ free(g);
+ free(y);
+ free(x);
+ free(v);
+ return 1;
+}
+#endif /* GCRYPT */
static int default_get_password(char *buf, int size,int rwflag, char *descr){
char *pass;
@@ -41,7 +460,7 @@ static int default_get_password(char *buf, int size,int rwflag, char *descr){
int len;
snprintf(buffer,256,"Please enter passphrase for %s",descr);
pass=getpass(buffer);
- snprintf(buf,size,"%s",buffer);
+ snprintf(buf,size,"%s",pass);
len=strlen(buf);
memset(pass,0,strlen(pass));
return len;
@@ -57,8 +476,14 @@ static int get_password_specified(char *buf,int size, int rwflag, char *password
PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session,char *filename,int type,char *passphrase){
FILE *file=fopen(filename,"r");
PRIVATE_KEY *privkey;
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_t dsa=NULL;
+ gcry_sexp_t rsa=NULL;
+ int valid;
+#elif defined HAVE_LIBCRYPTO
DSA *dsa=NULL;
RSA *rsa=NULL;
+#endif
if(!file){
ssh_set_error(session,SSH_REQUEST_DENIED,"Error opening %s : %s",filename,strerror(errno));
return NULL;
@@ -66,6 +491,17 @@ PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session,char *filename,int type,
if(type==TYPE_DSS){
if(!passphrase){
if(session && session->options->passphrase_function)
+#ifdef HAVE_LIBGCRYPT
+ valid = read_dsa_privatekey(file,&dsa, session->options->passphrase_function,"DSA private key");
+ else
+ valid = read_dsa_privatekey(file,&dsa,(void *)default_get_password, "DSA private key");
+ }
+ else
+ valid = read_dsa_privatekey(file,&dsa,(void *)get_password_specified,passphrase);
+ fclose(file);
+ if(!valid){
+ ssh_set_error(session,SSH_FATAL,"parsing private key %s",filename);
+#elif defined HAVE_LIBCRYPTO
dsa=PEM_read_DSAPrivateKey(file,NULL, session->options->passphrase_function,"DSA private key");
else
dsa=PEM_read_DSAPrivateKey(file,NULL,(void *)default_get_password, "DSA private key");
@@ -76,12 +512,24 @@ PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session,char *filename,int type,
if(!dsa){
ssh_set_error(session,SSH_FATAL,"parsing private key %s"
": %s",filename,ERR_error_string(ERR_get_error(),NULL));
+#endif
return NULL;
}
}
else if (type==TYPE_RSA){
if(!passphrase){
if(session && session->options->passphrase_function)
+#ifdef HAVE_LIBGCRYPT
+ valid = read_rsa_privatekey(file,&rsa, session->options->passphrase_function,"RSA private key");
+ else
+ valid = read_rsa_privatekey(file,&rsa,(void *)default_get_password, "RSA private key");
+ }
+ else
+ valid = read_rsa_privatekey(file,&rsa,(void *)get_password_specified,passphrase);
+ fclose(file);
+ if(!valid){
+ ssh_set_error(session,SSH_FATAL,"parsing private key %s",filename);
+#elif defined HAVE_LIBCRYPTO
rsa=PEM_read_RSAPrivateKey(file,NULL, session->options->passphrase_function,"RSA private key");
else
rsa=PEM_read_RSAPrivateKey(file,NULL,(void *)default_get_password, "RSA private key");
@@ -92,6 +540,7 @@ PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session,char *filename,int type,
if(!rsa){
ssh_set_error(session,SSH_FATAL,"parsing private key %s"
": %s",filename,ERR_error_string(ERR_get_error(),NULL));
+#endif
return NULL;
}
} else {
@@ -110,27 +559,49 @@ PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session,char *filename,int type,
PRIVATE_KEY *_privatekey_from_file(void *session,char *filename,int type){
FILE *file=fopen(filename,"r");
PRIVATE_KEY *privkey;
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_t dsa=NULL;
+ gcry_sexp_t rsa=NULL;
+ int valid;
+#elif defined HAVE_LIBCRYPTO
DSA *dsa=NULL;
RSA *rsa=NULL;
+#endif
if(!file){
ssh_set_error(session,SSH_REQUEST_DENIED,"Error opening %s : %s",filename,strerror(errno));
return NULL;
}
if(type==TYPE_DSS){
+#ifdef HAVE_LIBGCRYPT
+ valid=read_dsa_privatekey(file,&dsa,NULL,NULL);
+ fclose(file);
+ if(!valid){
+ ssh_set_error(session,SSH_FATAL,"parsing private key %s"
+ ,filename);
+#elif defined HAVE_LIBCRYPTO
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));
+#endif
return NULL;
}
}
else if (type==TYPE_RSA){
+#ifdef HAVE_LIBGCRYPT
+ valid=read_rsa_privatekey(file,&rsa,NULL,NULL);
+ fclose(file);
+ if(!valid){
+ ssh_set_error(session,SSH_FATAL,"parsing private key %s"
+ ,filename);
+#elif defined HAVE_LIBCRYPTO
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));
+#endif
return NULL;
}
} else {
@@ -145,10 +616,17 @@ PRIVATE_KEY *_privatekey_from_file(void *session,char *filename,int type){
}
void private_key_free(PRIVATE_KEY *prv){
+#ifdef HAVE_LIBGCRYPT
+ if(prv->dsa_priv)
+ gcry_sexp_release(prv->dsa_priv);
+ if(prv->rsa_priv)
+ gcry_sexp_release(prv->rsa_priv);
+#elif defined HAVE_LIBCRYPTO
if(prv->dsa_priv)
DSA_free(prv->dsa_priv);
if(prv->rsa_priv)
RSA_free(prv->rsa_priv);
+#endif
memset(prv,0,sizeof(PRIVATE_KEY));
free(prv);
}
@@ -359,7 +837,7 @@ int ssh_is_server_known(SSH_SESSION *session){
}
int ssh_write_knownhost(SSH_SESSION *session){
- char *pubkey_64;
+ unsigned char *pubkey_64;
STRING *pubkey=session->current_crypto->server_pubkey;
char buffer[4096];
FILE *file;
diff --git a/libssh/keys.c b/libssh/keys.c
index a5def00e..67ee08fb 100644
--- a/libssh/keys.c
+++ b/libssh/keys.c
@@ -20,9 +20,13 @@ 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 <string.h>
+#include <netinet/in.h>
+#ifdef HAVE_LIBCRYPTO
#include <openssl/dsa.h>
#include <openssl/rsa.h>
+#endif
#include "libssh/priv.h"
@@ -63,11 +67,15 @@ PUBLIC_KEY *publickey_make_dss(BUFFER *buffer){
free(key);
return NULL;
}
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_build(&key->dsa_pub,NULL,"(public-key(dsa(p %b)(q %b)(g %b)(y %b)))",string_len(p),p->string,string_len(q),q->string,string_len(g),g->string,string_len(pubkey),pubkey->string);
+#elif defined HAVE_LIBCRYPTO
key->dsa_pub=DSA_new();
key->dsa_pub->p=make_string_bn(p);
key->dsa_pub->q=make_string_bn(q);
key->dsa_pub->g=make_string_bn(g);
key->dsa_pub->pub_key=make_string_bn(pubkey);
+#endif
free(p);
free(q);
free(g);
@@ -95,12 +103,16 @@ PUBLIC_KEY *publickey_make_rsa(BUFFER *buffer, char *type){
free(key);
return NULL;
}
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_build(&key->rsa_pub,NULL,"(public-key(rsa(n %b)(e %b)))",string_len(n),n->string,string_len(e),e->string);
+#elif HAVE_LIBCRYPTO
key->rsa_pub=RSA_new();
key->rsa_pub->e=make_string_bn(e);
key->rsa_pub->n=make_string_bn(n);
+#endif
#ifdef DEBUG_CRYPTO
- ssh_print_bignum("e",key->rsa_pub->e);
- ssh_print_bignum("n",key->rsa_pub->n);
+ ssh_print_hexa("e",e->string,string_len(e));
+ ssh_print_hexa("n",n->string,string_len(n));
#endif
free(e);
free(n);
@@ -112,11 +124,19 @@ void publickey_free(PUBLIC_KEY *key){
return;
switch(key->type){
case TYPE_DSS:
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_release(key->dsa_pub);
+#elif HAVE_LIBCRYPTO
DSA_free(key->dsa_pub);
+#endif
break;
case TYPE_RSA:
case TYPE_RSA1:
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_release(key->rsa_pub);
+#elif defined HAVE_LIBCRYPTO
RSA_free(key->rsa_pub);
+#endif
break;
default:
break;
@@ -158,32 +178,112 @@ PUBLIC_KEY *publickey_from_string(STRING *pubkey_s){
PUBLIC_KEY *publickey_from_privatekey(PRIVATE_KEY *prv){
PUBLIC_KEY *key=malloc(sizeof(PUBLIC_KEY));
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_t sexp;
+ const char *tmp;
+ size_t size;
+ STRING *p,*q,*g,*y,*e,*n;
+#endif
key->type=prv->type;
switch(key->type){
case TYPE_DSS:
+#ifdef HAVE_LIBGCRYPT
+ sexp=gcry_sexp_find_token(prv->dsa_priv,"p",0);
+ tmp=gcry_sexp_nth_data(sexp,1,&size);
+ p=string_new(size);
+ string_fill(p,(char *)tmp,size);
+ gcry_sexp_release(sexp);
+ sexp=gcry_sexp_find_token(prv->dsa_priv,"q",0);
+ tmp=gcry_sexp_nth_data(sexp,1,&size);
+ q=string_new(size);
+ string_fill(q,(char *)tmp,size);
+ gcry_sexp_release(sexp);
+ sexp=gcry_sexp_find_token(prv->dsa_priv,"g",0);
+ tmp=gcry_sexp_nth_data(sexp,1,&size);
+ g=string_new(size);
+ string_fill(g,(char *)tmp,size);
+ gcry_sexp_release(sexp);
+ sexp=gcry_sexp_find_token(prv->dsa_priv,"y",0);
+ tmp=gcry_sexp_nth_data(sexp,1,&size);
+ y=string_new(size);
+ string_fill(y,(char *)tmp,size);
+ gcry_sexp_release(sexp);
+ gcry_sexp_build(&key->dsa_pub,NULL,"(public-key(dsa(p %b)(q %b)(g %b)(y %b)))",string_len(p),p->string,string_len(q),q->string,string_len(g),g->string,string_len(y),y->string);
+ free(p);
+ free(q);
+ free(g);
+ free(y);
+#elif defined HAVE_LIBCRYPTO
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);
+#endif
break;
case TYPE_RSA:
case TYPE_RSA1:
+#ifdef HAVE_LIBGCRYPT
+ sexp=gcry_sexp_find_token(prv->rsa_priv,"n",0);
+ tmp=gcry_sexp_nth_data(sexp,1,&size);
+ n=string_new(size);
+ string_fill(n,(char *)tmp,size);
+ gcry_sexp_release(sexp);
+ sexp=gcry_sexp_find_token(prv->rsa_priv,"e",0);
+ tmp=gcry_sexp_nth_data(sexp,1,&size);
+ e=string_new(size);
+ string_fill(e,(char *)tmp,size);
+ gcry_sexp_release(sexp);
+ gcry_sexp_build(&key->rsa_pub,NULL,"(public-key(rsa(n %b)(e %b)))",string_len(n),n->string,string_len(e),e->string);
+ free(e);
+ free(n);
+#elif defined HAVE_LIBCRYPTO
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);
+#endif
break;
}
key->type_c=ssh_type_to_char(prv->type);
return key;
}
+#ifdef HAVE_LIBGCRYPT
+static void dsa_public_to_string(gcry_sexp_t key, BUFFER *buffer){
+#elif defined HAVE_LIBCRYPTO
static void dsa_public_to_string(DSA *key, BUFFER *buffer){
+#endif
STRING *p,*q,*g,*n;
+#ifdef HAVE_LIBGCRYPT
+ const char *tmp;
+ size_t size;
+ gcry_sexp_t sexp;
+ sexp=gcry_sexp_find_token(key,"p",0);
+ tmp=gcry_sexp_nth_data(sexp,1,&size);
+ p=string_new(size);
+ string_fill(p,(char *)tmp,size);
+ gcry_sexp_release(sexp);
+ sexp=gcry_sexp_find_token(key,"q",0);
+ tmp=gcry_sexp_nth_data(sexp,1,&size);
+ q=string_new(size);
+ string_fill(q,(char *)tmp,size);
+ gcry_sexp_release(sexp);
+ sexp=gcry_sexp_find_token(key,"g",0);
+ tmp=gcry_sexp_nth_data(sexp,1,&size);
+ g=string_new(size);
+ string_fill(g,(char *)tmp,size);
+ gcry_sexp_release(sexp);
+ sexp=gcry_sexp_find_token(key,"y",0);
+ tmp=gcry_sexp_nth_data(sexp,1,&size);
+ n=string_new(size);
+ string_fill(n,(char *)tmp,size);
+ gcry_sexp_release(sexp);
+#elif defined HAVE_LIBCRYPTO
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);
+#endif
buffer_add_ssh_string(buffer,p);
buffer_add_ssh_string(buffer,q);
buffer_add_ssh_string(buffer,g);
@@ -194,10 +294,30 @@ static void dsa_public_to_string(DSA *key, BUFFER *buffer){
free(n);
}
+#ifdef HAVE_LIBGCRYPT
+static void rsa_public_to_string(gcry_sexp_t key, BUFFER *buffer){
+#elif defined HAVE_LIBCRYPTO
static void rsa_public_to_string(RSA *key, BUFFER *buffer){
+#endif
STRING *e, *n;
+#ifdef HAVE_LIBGCRYPT
+ const char *tmp;
+ size_t size;
+ gcry_sexp_t sexp;
+ sexp=gcry_sexp_find_token(key,"n",0);
+ tmp=gcry_sexp_nth_data(sexp,1,&size);
+ n=string_new(size);
+ string_fill(n,(char *)tmp,size);
+ gcry_sexp_release(sexp);
+ sexp=gcry_sexp_find_token(key,"e",0);
+ tmp=gcry_sexp_nth_data(sexp,1,&size);
+ e=string_new(size);
+ string_fill(e,(char *)tmp,size);
+ gcry_sexp_release(sexp);
+#elif defined HAVE_LIBCRYPTO
e=make_bignum_string(key->e);
n=make_bignum_string(key->n);
+#endif
buffer_add_ssh_string(buffer,e);
buffer_add_ssh_string(buffer,n);
free(e);
@@ -231,7 +351,14 @@ STRING *publickey_to_string(PUBLIC_KEY *key){
STRING *signature_to_string(SIGNATURE *sign){
STRING *str;
- STRING *rs,*r,*s;
+ STRING *rs;
+#ifdef HAVE_LIBGCRYPT
+ const char *r,*s;
+ gcry_sexp_t sexp;
+ size_t size;
+#elif defined HAVE_LIBCRYPTO
+ STRING *r,*s;
+#endif
unsigned char buffer[40];
BUFFER *tmpbuf=buffer_new();
STRING *tmp;
@@ -240,21 +367,58 @@ STRING *signature_to_string(SIGNATURE *sign){
free(tmp);
switch(sign->type){
case TYPE_DSS:
+ memset(buffer,0,40);
+#ifdef HAVE_LIBGCRYPT
+ sexp=gcry_sexp_find_token(sign->dsa_sign,"r",0);
+ r=gcry_sexp_nth_data(sexp,1,&size);
+ if (*r == 0) /* libgcrypt put 0 when first bit is set */
+ {
+ size--;
+ r++;
+ }
+ memcpy(buffer,r + size - 20,20);
+ gcry_sexp_release(sexp);
+ sexp=gcry_sexp_find_token(sign->dsa_sign,"s",0);
+ s=gcry_sexp_nth_data(sexp,1,&size);
+ if (*s == 0)
+ {
+ size--;
+ s++;
+ }
+ memcpy(buffer+ 20, s + size - 20, 20);
+ gcry_sexp_release(sexp);
+#elif defined HAVE_LIBCRYPTO
r=make_bignum_string(sign->dsa_sign->r);
s=make_bignum_string(sign->dsa_sign->s);
rs=string_new(40);
- memset(buffer,0,40);
memcpy(buffer,r->string+string_len(r)-20,20);
memcpy(buffer+ 20, s->string + string_len(s) - 20, 20);
- string_fill(rs,buffer,40);
free(r);
free(s);
+#endif
+ rs=string_new(40);
+ string_fill(rs,buffer,40);
buffer_add_ssh_string(tmpbuf,rs);
free(rs);
break;
case TYPE_RSA:
case TYPE_RSA1:
+#ifdef HAVE_LIBGCRYPT
+ sexp=gcry_sexp_find_token(sign->rsa_sign,"s",0);
+ s=gcry_sexp_nth_data(sexp,1,&size);
+ if (*s == 0)
+ {
+ size--;
+ s++;
+ }
+ rs=string_new(size);
+ string_fill(rs,(char *)s,size);
+ buffer_add_ssh_string(tmpbuf,rs);
+ gcry_sexp_release(sexp);
+ free(rs);
+#elif defined HAVE_LIBCRYPTO
buffer_add_ssh_string(tmpbuf,sign->rsa_sign);
+#endif
break;
}
str=string_new(buffer_get_len(tmpbuf));
@@ -265,11 +429,16 @@ STRING *signature_to_string(SIGNATURE *sign){
/* TODO : split this function in two so it becomes smaller */
SIGNATURE *signature_from_string(STRING *signature,PUBLIC_KEY *pubkey,int needed_type){
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_t sig;
+#elif defined HAVE_LIBCRYPTO
DSA_SIG *sig;
+ STRING *r,*s;
+#endif
SIGNATURE *sign=malloc(sizeof(SIGNATURE));
BUFFER *tmpbuf=buffer_new();
STRING *rs;
- STRING *r,*s,*type_s,*e;
+ STRING *type_s,*e;
int len,rsalen;
char *type;
buffer_add_data(tmpbuf,signature->string,string_len(signature));
@@ -314,21 +483,25 @@ SIGNATURE *signature_from_string(STRING *signature,PUBLIC_KEY *pubkey,int needed
free(rs);
return NULL;
}
- /* we make use of strings because we have all-made functions to convert them to bignums */
+ /* we make use of strings (because we have all-made functions to convert them to bignums (ou pas ;)*/
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_build(&sig,NULL,"(sig-val(dsa(r %b)(s %b)))",20,rs->string,20,rs->string+20);
+#elif defined HAVE_LIBCRYPTO
r=string_new(20);
s=string_new(20);
string_fill(r,rs->string,20);
string_fill(s,rs->string+20,20);
- free(rs);
sig=DSA_SIG_new();
sig->r=make_string_bn(r); /* is that really portable ? Openssh's hack isn't better */
sig->s=make_string_bn(s);
-#ifdef DEBUG_CRYPTO
- ssh_print_bignum("r",sig->r);
- ssh_print_bignum("s",sig->s);
-#endif
free(r);
free(s);
+#endif
+#ifdef DEBUG_CRYPTO
+ ssh_print_hexa("r",rs->string,20);
+ ssh_print_hexa("s",rs->string+20,20);
+#endif
+ free(rs);
sign->type=TYPE_DSS;
sign->dsa_sign=sig;
return sign;
@@ -336,11 +509,14 @@ SIGNATURE *signature_from_string(STRING *signature,PUBLIC_KEY *pubkey,int needed
e=buffer_get_ssh_string(tmpbuf);
buffer_free(tmpbuf);
if(!e){
- free(e);
- return NULL;
+ return NULL;
}
len=string_len(e);
+#ifdef HAVE_LIBGCRYPT
+ rsalen=(gcry_pk_get_nbits(pubkey->rsa_pub)+7)/8;
+#elif defined HAVE_LIBCRYPTO
rsalen=RSA_size(pubkey->rsa_pub);
+#endif
if(len>rsalen){
free(e);
free(sign);
@@ -350,11 +526,19 @@ SIGNATURE *signature_from_string(STRING *signature,PUBLIC_KEY *pubkey,int needed
if(len<rsalen)
ssh_say(0,"Len %d < %d\n",len,rsalen);
sign->type=TYPE_RSA;
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_build(&sig,NULL,"(sig-val(rsa(s %b)))",string_len(e),e->string);
+ sign->rsa_sign=sig;
+#elif defined HAVE_LIBCRYPTO
sign->rsa_sign=e;
+#endif
#ifdef DEBUG_CRYPTO
ssh_say(0,"Len : %d\n",len);
ssh_print_hexa("rsa signature",e->string,len);
#endif
+#ifdef HAVE_LIBGCRYPT
+ free(e);
+#endif
return sign;
default:
return NULL;
@@ -366,11 +550,19 @@ void signature_free(SIGNATURE *sign){
return;
switch(sign->type){
case TYPE_DSS:
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_release(sign->dsa_sign);
+#elif defined HAVE_LIBCRYPTO
DSA_SIG_free(sign->dsa_sign);
+#endif
break;
case TYPE_RSA:
case TYPE_RSA1:
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_release(sign->rsa_sign);
+#elif defined HAVE_LIBCRYPTO
free(sign->rsa_sign);
+#endif
break;
default:
ssh_say(1,"freeing a signature with no type !\n");
@@ -378,6 +570,7 @@ void signature_free(SIGNATURE *sign){
free(sign);
}
+#ifdef HAVE_LIBCRYPTO
/* maybe the missing function from libcrypto */
/* i think now, maybe it's a bad idea to name it has it should have be named in libcrypto */
static STRING *RSA_do_sign(void *payload,int len,RSA *privkey){
@@ -395,42 +588,64 @@ static STRING *RSA_do_sign(void *payload,int len,RSA *privkey){
free(buffer);
return sign;
}
+#endif
/* 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;
+ SHACTX ctx;
STRING *session_str=string_new(SHA_DIGEST_LEN);
- char hash[SHA_DIGEST_LEN];
+ unsigned char hash[SHA_DIGEST_LEN+1];
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_t gcryhash;
+#endif
SIGNATURE *sign;
STRING *signature;
CRYPTO *crypto=session->current_crypto?session->current_crypto:session->next_crypto;
- string_fill(session_str,crypto->session_id,SHA_DIGEST_LENGTH);
+ string_fill(session_str,crypto->session_id,SHA_DIGEST_LEN);
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);
+ sha1_final(hash+1,ctx);
+ hash[0]=0;
#ifdef DEBUG_CRYPTO
- ssh_print_hexa("Hash being signed with dsa",hash,SHA_DIGEST_LENGTH);
+ ssh_print_hexa("Hash being signed with dsa",hash+1,SHA_DIGEST_LEN);
#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 HAVE_LIBGCRYPT
+ gcry_sexp_build(&gcryhash,NULL,"%b",SHA_DIGEST_LEN+1,hash);
+ gcry_pk_sign(&sign->dsa_sign,gcryhash,privatekey->dsa_priv);
+#elif defined HAVE_LIBCRYPTO
+ sign->dsa_sign=DSA_do_sign(hash+1,SHA_DIGEST_LEN,privatekey->dsa_priv);
#ifdef DEBUG_CRYPTO
ssh_print_bignum("r",sign->dsa_sign->r);
ssh_print_bignum("s",sign->dsa_sign->s);
#endif
+#endif
sign->rsa_sign=NULL;
break;
case TYPE_RSA:
- sign->rsa_sign=RSA_do_sign(hash,SHA_DIGEST_LENGTH,privatekey->rsa_priv);
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_build(&gcryhash,NULL,"(data(flags pkcs1)(hash sha1 %b))",SHA_DIGEST_LEN,hash+1);
+ gcry_pk_sign(&sign->rsa_sign,gcryhash,privatekey->rsa_priv);
+#elif defined HAVE_LIBCRYPTO
+ sign->rsa_sign=RSA_do_sign(hash+1,SHA_DIGEST_LEN,privatekey->rsa_priv);
+#endif
sign->dsa_sign=NULL;
break;
}
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_release(gcryhash);
+#endif
sign->type=privatekey->type;
if(!sign->dsa_sign && !sign->rsa_sign){
+#ifdef HAVE_LIBGCRYPT
+ ssh_set_error(session,SSH_FATAL,"Signing : libcrypt error");
+#elif HAVE_LIBCRYPTO
ssh_set_error(session,SSH_FATAL,"Signing : openssl error");
+#endif
signature_free(sign);
return NULL;
}
@@ -441,45 +656,87 @@ STRING *ssh_do_sign(SSH_SESSION *session,BUFFER *sigbuf, PRIVATE_KEY *privatekey
STRING *ssh_encrypt_rsa1(SSH_SESSION *session, STRING *data, PUBLIC_KEY *key){
int len=string_len(data);
+#ifdef HAVE_LIBGCRYPT
+ STRING *ret;
+ gcry_sexp_t ret_sexp;
+ gcry_sexp_t data_sexp;
+ const char *tmp;
+ size_t size;
+ gcry_sexp_build(&data_sexp,NULL,"(data(flags pkcs1)(value %b))",len,data->string);
+ gcry_pk_encrypt(&ret_sexp,data_sexp,key->rsa_pub);
+ gcry_sexp_release(data_sexp);
+ data_sexp=gcry_sexp_find_token(ret_sexp,"a",0);
+ tmp=gcry_sexp_nth_data(data_sexp,1,&size);
+ if (*tmp == 0)
+ {
+ size--;
+ tmp++;
+ }
+ ret=string_new(size);
+ string_fill(ret,(char *)tmp,size);
+ gcry_sexp_release(ret_sexp);
+#elif defined HAVE_LIBCRYPTO
int flen=RSA_size(key->rsa_pub);
STRING *ret=string_new(flen);
RSA_public_encrypt(len,data->string,ret->string,key->rsa_pub,
RSA_PKCS1_PADDING);
+#endif
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];
+ SHACTX ctx;
+ unsigned char hash[SHA_DIGEST_LEN+1];
SIGNATURE *sign;
STRING *signature;
CRYPTO *crypto=session->current_crypto?session->current_crypto:session->next_crypto;
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_t data_sexp;
+#endif
ctx=sha1_init();
- sha1_update(ctx,crypto->session_id,SHA_DIGEST_LENGTH);
- sha1_final(hash,ctx);
+ sha1_update(ctx,crypto->session_id,SHA_DIGEST_LEN);
+ sha1_final(hash+1,ctx);
+ hash[0]=0;
#ifdef DEBUG_CRYPTO
- ssh_print_hexa("Hash being signed with dsa",hash,SHA_DIGEST_LENGTH);
+ ssh_print_hexa("Hash being signed with dsa",hash+1,SHA_DIGEST_LEN);
#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 HAVE_LIBGCRYPT
+ gcry_sexp_build(&data_sexp,NULL,"%b",SHA_DIGEST_LEN+1,hash);
+ gcry_pk_sign(&sign->dsa_sign,data_sexp,privatekey->dsa_priv);
+#elif defined HAVE_LIBCRYPTO
+ sign->dsa_sign=DSA_do_sign(hash+1,SHA_DIGEST_LEN,privatekey->dsa_priv);
#ifdef DEBUG_CRYPTO
ssh_print_bignum("r",sign->dsa_sign->r);
ssh_print_bignum("s",sign->dsa_sign->s);
#endif
+#endif
sign->rsa_sign=NULL;
break;
case TYPE_RSA:
- sign->rsa_sign=RSA_do_sign(hash,SHA_DIGEST_LENGTH,privatekey->rsa_priv);
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_build(&data_sexp,NULL,"(data(flags pkcs1)(hash sha1 %b))",SHA_DIGEST_LEN,hash+1);
+ gcry_pk_sign(&sign->rsa_sign,data_sexp,privatekey->rsa_priv);
+#elif defined HAVE_LIBCRYPTO
+ sign->rsa_sign=RSA_do_sign(hash+1,SHA_DIGEST_LEN,privatekey->rsa_priv);
+#endif
sign->dsa_sign=NULL;
break;
}
+#ifdef HAVE_LIBGCRYPT
+ gcry_sexp_release(data_sexp);
+#endif
sign->type=privatekey->type;
if(!sign->dsa_sign && !sign->rsa_sign){
+#ifdef HAVE_LIBGCRYPT
+ ssh_set_error(session,SSH_FATAL,"Signing : libgcrypt error");
+#elif defined HAVE_LIBCRYPTO
ssh_set_error(session,SSH_FATAL,"Signing : openssl error");
+#endif
signature_free(sign);
return NULL;
}
diff --git a/libssh/messages.c b/libssh/messages.c
index 6523f1c7..d8c16ed1 100644
--- a/libssh/messages.c
+++ b/libssh/messages.c
@@ -32,6 +32,7 @@ MA 02111-1307, USA. */
#include "libssh/ssh2.h"
#include <netdb.h>
#include <string.h>
+#include <stdlib.h>
static SSH_MESSAGE *message_new(SSH_SESSION *session){
SSH_MESSAGE *msg=session->ssh_message;
diff --git a/libssh/packet.c b/libssh/packet.c
index e717ba59..4085f60d 100644
--- a/libssh/packet.c
+++ b/libssh/packet.c
@@ -32,7 +32,7 @@ MA 02111-1307, USA. */
#include "libssh/crypto.h"
/* XXX include selected mac size */
-static int macsize=SHA_DIGEST_LENGTH;
+static int macsize=SHA_DIGEST_LEN;
/* completeread will read blocking until len bytes have been read */
static int completeread(int fd, void *buffer, int len){
@@ -55,7 +55,7 @@ static int completeread(int fd, void *buffer, int len){
static int packet_read2(SSH_SESSION *session){
u32 len;
void *packet=NULL;
- char mac[30];
+ unsigned char mac[30];
char buffer[16];
int be_read,i;
int to_be_read;
@@ -316,7 +316,7 @@ static int packet_send2(SSH_SESSION *session){
u32 finallen;
u8 padding;
u32 currentlen=buffer_get_len(session->out_buffer);
- char *hmac;
+ unsigned char *hmac;
int ret=0;
unsigned int blocksize=(session->current_crypto?session->current_crypto->out_cipher->blocksize:8);
ssh_say(3,"Writing on the wire a packet having %ld bytes before",currentlen);
diff --git a/libssh/server.c b/libssh/server.c
index 0f429852..4a915889 100644
--- a/libssh/server.c
+++ b/libssh/server.c
@@ -27,10 +27,10 @@ MA 02111-1307, USA. */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
-#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <string.h>
+#include <stdlib.h>
#include "libssh/libssh.h"
#include "libssh/server.h"
#include "libssh/ssh2.h"
diff --git a/libssh/session.c b/libssh/session.c
index 1a0f25ce..b084c29d 100644
--- a/libssh/session.c
+++ b/libssh/session.c
@@ -22,6 +22,7 @@
/* ssh_new() returns a newly allocated SSH_SESSION structure pointer */
#include <string.h>
+#include <stdlib.h>
#include "libssh/libssh.h"
#include "libssh/priv.h"
#include "libssh/server.h"
diff --git a/libssh/sftp.c b/libssh/sftp.c
index 3c7e7410..5a49fb7b 100644
--- a/libssh/sftp.c
+++ b/libssh/sftp.c
@@ -22,6 +22,7 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA. */
+#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <netdb.h>
diff --git a/libssh/sftpserver.c b/libssh/sftpserver.c
index bfbbc400..7779512a 100644
--- a/libssh/sftpserver.c
+++ b/libssh/sftpserver.c
@@ -26,6 +26,7 @@ MA 02111-1307, USA. */
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
+#include <stdio.h>
SFTP_CLIENT_MESSAGE *sftp_get_client_message(SFTP_SESSION *sftp){
SFTP_PACKET *packet=sftp_packet_read(sftp);
diff --git a/libssh/string.c b/libssh/string.c
index 2f14c141..2e6c3bfd 100644
--- a/libssh/string.c
+++ b/libssh/string.c
@@ -26,7 +26,7 @@ MA 02111-1307, USA. */
#include <string.h>
#include "libssh/priv.h"
-STRING *string_new(u32 size){
+STRING *string_new(unsigned int size){
STRING *str=malloc(size + 4);
str->size=htonl(size);
return str;
diff --git a/libssh/wrapper.c b/libssh/wrapper.c
index 9d418df0..92a25a90 100644
--- a/libssh/wrapper.c
+++ b/libssh/wrapper.c
@@ -27,8 +27,178 @@ MA 02111-1307, USA. */
#include "libssh/priv.h"
#include "libssh/crypto.h"
+#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
-#ifdef OPENSSL_CRYPTO
+#ifdef HAVE_LIBGCRYPT
+#include <gcrypt.h>
+
+SHACTX sha1_init(){
+ SHACTX ret;
+ gcry_md_open(&ret,GCRY_MD_SHA1,GCRY_MD_FLAG_SECURE);
+ return ret;
+}
+void sha1_update(SHACTX c, const void *data, unsigned long len){
+ gcry_md_write(c,data,len);
+}
+void sha1_final(unsigned char *md,SHACTX c){
+ gcry_md_final(c);
+ memcpy(md, gcry_md_read(c, 0), SHA_DIGEST_LEN);
+ gcry_md_close(c);
+}
+void sha1(unsigned char *digest,int len,unsigned char *hash){
+ gcry_md_hash_buffer(GCRY_MD_SHA1,hash,digest,len);
+}
+
+MD5CTX md5_init(){
+ MD5CTX ret;
+ gcry_md_open(&ret,GCRY_MD_MD5,GCRY_MD_FLAG_SECURE);
+ return ret;
+}
+void md5_update(MD5CTX c, const void *data, unsigned long len){
+ gcry_md_write(c,data,len);
+}
+void md5_final(unsigned char *md,MD5CTX c){
+ gcry_md_final(c);
+ memcpy(md, gcry_md_read(c, 0), MD5_DIGEST_LEN);
+ gcry_md_close(c);
+}
+
+HMACCTX hmac_init(const void *key, int len,int type){
+ HMACCTX c;
+ switch(type){
+ case HMAC_SHA1:
+ gcry_md_open(&c,GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE);
+ break;
+ case HMAC_MD5:
+ gcry_md_open(&c,GCRY_MD_MD5, GCRY_MD_FLAG_HMAC | GCRY_MD_FLAG_SECURE);
+ break;
+ default:
+ c=NULL;
+ }
+ gcry_md_setkey(c,key,len);
+ return c;
+}
+void hmac_update(HMACCTX c, const void *data, unsigned long len){
+ gcry_md_write(c,data,len);
+}
+
+void hmac_final(HMACCTX c,unsigned char *hashmacbuf,unsigned int *len){
+ *len = gcry_md_get_algo_dlen(gcry_md_get_algo(c));
+ memcpy(hashmacbuf, gcry_md_read(c, 0), *len);
+ gcry_md_close(c);
+}
+
+static void alloc_key(struct crypto_struct *cipher){
+ cipher->key=malloc(cipher->keylen);
+}
+
+/* the wrapper functions for blowfish */
+static void blowfish_set_key(struct crypto_struct *cipher, void *key, void *IV){
+ if(!cipher->key){
+ alloc_key(cipher);
+ gcry_cipher_open(&cipher->key[0],GCRY_CIPHER_BLOWFISH,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_SECURE);
+ gcry_cipher_setkey(cipher->key[0],key,16);
+ gcry_cipher_setiv(cipher->key[0],IV,8);
+ }
+}
+
+static void blowfish_encrypt(struct crypto_struct *cipher, void *in, void *out,unsigned long len){
+ gcry_cipher_encrypt(cipher->key[0],out,len,in,len);
+}
+
+static void blowfish_decrypt(struct crypto_struct *cipher, void *in, void *out, unsigned long len){
+ gcry_cipher_decrypt(cipher->key[0],out,len,in,len);
+}
+
+static void aes_set_key(struct crypto_struct *cipher, void *key, void *IV){
+ if(!cipher->key){
+ alloc_key(cipher);
+ switch(cipher->keysize){
+ case 128:
+ gcry_cipher_open(&cipher->key[0],GCRY_CIPHER_AES128,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_SECURE);
+ break;
+ case 192:
+ gcry_cipher_open(&cipher->key[0],GCRY_CIPHER_AES192,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_SECURE);
+ break;
+ case 256:
+ gcry_cipher_open(&cipher->key[0],GCRY_CIPHER_AES256,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_SECURE);
+ break;
+ }
+ gcry_cipher_setkey(cipher->key[0],key,cipher->keysize/8);
+ gcry_cipher_setiv(cipher->key[0], IV, 16);
+ }
+}
+
+static void aes_encrypt(struct crypto_struct *cipher, void *in, void *out, unsigned long len){
+ gcry_cipher_encrypt(cipher->key[0],out,len,in,len);
+}
+
+static void aes_decrypt(struct crypto_struct *cipher, void *in, void *out,unsigned long len){
+ gcry_cipher_decrypt(cipher->key[0],out,len,in,len);
+}
+
+static void des3_set_key(struct crypto_struct *cipher, void *key, void *IV){
+ if(!cipher->key){
+ alloc_key(cipher);
+ gcry_cipher_open(&cipher->key[0],GCRY_CIPHER_3DES,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_SECURE);
+ gcry_cipher_setkey(cipher->key[0],key,24);
+ gcry_cipher_setiv(cipher->key[0],IV,8);
+ }
+}
+
+static void des3_encrypt(struct crypto_struct *cipher, void *in, void *out,
+ unsigned long len){
+ gcry_cipher_encrypt(cipher->key[0],out,len,in,len);
+}
+
+static void des3_decrypt(struct crypto_struct *cipher, void *in, void *out,
+ unsigned long len){
+ gcry_cipher_decrypt(cipher->key[0],out,len,in,len);
+}
+
+static void des3_1_set_key(struct crypto_struct *cipher, void *key, void *IV){
+ if(!cipher->key){
+ alloc_key(cipher);
+ gcry_cipher_open(&cipher->key[0],GCRY_CIPHER_DES,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_SECURE);
+ gcry_cipher_setkey(cipher->key[0],key,8);
+ gcry_cipher_setiv(cipher->key[0],IV,8);
+ gcry_cipher_open(&cipher->key[1],GCRY_CIPHER_DES,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_SECURE);
+ gcry_cipher_setkey(cipher->key[1],key+8,8);
+ gcry_cipher_setiv(cipher->key[1],IV+8,8);
+ gcry_cipher_open(&cipher->key[2],GCRY_CIPHER_DES,GCRY_CIPHER_MODE_CBC,GCRY_CIPHER_SECURE);
+ gcry_cipher_setkey(cipher->key[2],key+16,8);
+ gcry_cipher_setiv(cipher->key[2],IV+16,8);
+ }
+}
+
+static void des3_1_encrypt(struct crypto_struct *cipher, void *in, void *out,
+ unsigned long len){
+ gcry_cipher_encrypt(cipher->key[0],out,len,in,len);
+ gcry_cipher_decrypt(cipher->key[1],in,len,out,len);
+ gcry_cipher_encrypt(cipher->key[2],out,len,in,len);
+}
+
+static void des3_1_decrypt(struct crypto_struct *cipher, void *in, void *out,
+ unsigned long len){
+ gcry_cipher_decrypt(cipher->key[2],out,len,in,len);
+ gcry_cipher_encrypt(cipher->key[1],in,len,out,len);
+ gcry_cipher_decrypt(cipher->key[0],out,len,in,len);
+}
+
+/* the table of supported ciphers */
+static struct crypto_struct ssh_ciphertab[]={
+ { "blowfish-cbc", 8 ,sizeof (gcry_cipher_hd_t),NULL,128,blowfish_set_key,blowfish_set_key,blowfish_encrypt, blowfish_decrypt},
+ { "aes128-cbc",16,sizeof(gcry_cipher_hd_t),NULL,128,aes_set_key,aes_set_key,aes_encrypt,aes_decrypt},
+ { "aes192-cbc",16,sizeof(gcry_cipher_hd_t),NULL,192,aes_set_key,aes_set_key,aes_encrypt,aes_decrypt},
+ { "aes256-cbc",16,sizeof(gcry_cipher_hd_t),NULL,256,aes_set_key,aes_set_key,aes_encrypt,aes_decrypt},
+ { "3des-cbc",8,sizeof(gcry_cipher_hd_t),NULL,192,des3_set_key,
+ des3_set_key,des3_encrypt, des3_decrypt},
+ { "3des-cbc-ssh1",8,sizeof(gcry_cipher_hd_t)*3,NULL,192,des3_1_set_key,
+ des3_1_set_key,des3_1_encrypt, des3_1_decrypt},
+ { NULL,0,0,NULL,0,NULL,NULL,NULL}
+};
+#elif defined HAVE_LIBCRYPTO
#include <openssl/sha.h>
#include <openssl/md5.h>
#include <openssl/dsa.h>
@@ -43,22 +213,24 @@ MA 02111-1307, USA. */
#define HAS_BLOWFISH
#include <openssl/blowfish.h>
#endif
-
+#ifdef HAVE_OPENSSL_DES_H
+#define HAS_DES
#include <openssl/des.h>
+#endif
#if (OPENSSL_VERSION_NUMBER<0x009070000)
#define OLD_CRYPTO
#endif
-SHACTX *sha1_init(){
- SHACTX *c=malloc(sizeof(SHACTX));
+SHACTX sha1_init(){
+ SHACTX c=malloc(sizeof(*c));
SHA1_Init(c);
return c;
}
-void sha1_update(SHACTX *c, const void *data, unsigned long len){
+void sha1_update(SHACTX c, const void *data, unsigned long len){
SHA1_Update(c,data,len);
}
-void sha1_final(unsigned char *md,SHACTX *c){
+void sha1_final(unsigned char *md,SHACTX c){
SHA1_Final(md,c);
free(c);
}
@@ -66,21 +238,21 @@ void sha1(unsigned char *digest,int len,unsigned char *hash){
SHA1(digest,len,hash);
}
-MD5CTX *md5_init(){
- MD5CTX *c=malloc(sizeof(MD5CTX));
+MD5CTX md5_init(){
+ MD5CTX c=malloc(sizeof(MD5CTX));
MD5_Init(c);
return c;
}
-void md5_update(MD5CTX *c, const void *data, unsigned long len){
+void md5_update(MD5CTX c, const void *data, unsigned long len){
MD5_Update(c,data,len);
}
-void md5_final(unsigned char *md,MD5CTX *c){
+void md5_final(unsigned char *md,MD5CTX c){
MD5_Final(md,c);
free(c);
}
-HMACCTX *hmac_init(const void *key, int len,int type){
- HMAC_CTX *ctx;
+HMACCTX hmac_init(const void *key, int len,int type){
+ HMACCTX ctx;
ctx=malloc(sizeof(HMAC_CTX));
#ifndef OLD_CRYPTO
HMAC_CTX_init(ctx); // openssl 0.9.7 requires it.
@@ -98,10 +270,10 @@ HMACCTX *hmac_init(const void *key, int len,int type){
}
return ctx;
}
-void hmac_update(HMACCTX *ctx,const void *data, unsigned long len){
+void hmac_update(HMACCTX ctx,const void *data, unsigned long len){
HMAC_Update(ctx,data,len);
}
-void hmac_final(HMACCTX *ctx,unsigned char *hashmacbuf,int *len){
+void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len){
HMAC_Final(ctx,hashmacbuf,len);
#ifndef OLD_CRYPTO
HMAC_CTX_cleanup(ctx);
@@ -152,7 +324,7 @@ static void aes_decrypt(struct crypto_struct *cipher, void *in, void *out, unsig
AES_cbc_encrypt(in,out,len,cipher->key,IV,AES_DECRYPT);
}
#endif
-
+#ifdef HAS_DES
static void des3_set_key(struct crypto_struct *cipher, void *key){
if(!cipher->key){
alloc_key(cipher);
@@ -205,10 +377,8 @@ static void des3_1_decrypt(struct crypto_struct *cipher, void *in, void *out,
ssh_print_hexa("decrypt IV after",IV,24);
#endif
}
+#endif
-
-
-
/* the table of supported ciphers */
static struct crypto_struct ssh_ciphertab[]={
#ifdef HAS_BLOWFISH
@@ -223,10 +393,12 @@ static struct crypto_struct ssh_ciphertab[]={
{ "aes256-cbc",16,sizeof(AES_KEY),NULL,256,aes_set_encrypt_key,
aes_set_decrypt_key,aes_encrypt,aes_decrypt},
#endif
+#ifdef HAS_DES
{ "3des-cbc",8,sizeof(DES_key_schedule)*3,NULL,192,des3_set_key,
des3_set_key,des3_encrypt, des3_decrypt},
{ "3des-cbc-ssh1",8,sizeof(DES_key_schedule)*3,NULL,192,des3_set_key,
des3_set_key,des3_1_encrypt, des3_1_decrypt},
+#endif
{ NULL,0,0,NULL,0,NULL,NULL,NULL}
};
#endif /* OPENSSL_CRYPTO */
@@ -240,9 +412,17 @@ struct crypto_struct *cipher_new(int offset){
}
void cipher_free(struct crypto_struct *cipher){
+#ifdef HAVE_LIBGCRYPT
+ int i;
+#endif
if(cipher->key){
- // destroy the key
+#ifdef HAVE_LIBGCRYPT
+ for (i=0;i<cipher->keylen/sizeof (gcry_cipher_hd_t);i++)
+ gcry_cipher_close(cipher->key[i]);
+#elif defined HAVE_LIBCRYPTO
+ /* destroy the key */
memset(cipher->key,0,cipher->keylen);
+#endif
free(cipher->key);
}
free(cipher);
diff --git a/sample.c b/sample.c
index fbf5bef0..d25ecf58 100644
--- a/sample.c
+++ b/sample.c
@@ -358,7 +358,7 @@ int main(int argc, char **argv){
char *banner;
int state;
char buf[10];
- char hash[MD5_DIGEST_LEN];
+ unsigned char hash[MD5_DIGEST_LEN];
options=ssh_options_new();
if(ssh_options_getopt(options,&argc, argv))
diff --git a/samplesshd.c b/samplesshd.c
index 12ea7e2c..d51ac318 100644
--- a/samplesshd.c
+++ b/samplesshd.c
@@ -24,6 +24,7 @@ MA 02111-1307, USA. */
#include <libssh/server.h>
#include <unistd.h>
#include <string.h>
+#include <stdio.h>
int auth_password(char *user, char *password){
if(strcmp(user,"aris"))