added the gcrypt patch (without gcrypt as default library).
still needs tests. git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@38 7dcaeef0-15fb-0310-b436-a5af3365683c
Этот коммит содержится в:
родитель
c0525750fd
Коммит
5f7c84f900
@ -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
|
||||
|
||||
|
15
configure
поставляемый
15
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
|
||||
@ -3692,10 +3696,13 @@ 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
|
||||
|
15
configure.in
15
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
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 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
|
||||
|
||||
#ifdef OPENSSL_CRYPTO
|
||||
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);
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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){
|
||||
|
@ -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);
|
||||
|
@ -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].
|
||||
|
||||
*/
|
@ -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(){
|
||||
|
@ -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 ... */
|
||||
|
@ -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));
|
||||
|
169
libssh/dh.c
169
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");
|
||||
|
@ -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){
|
||||
|
13
libssh/kex.c
13
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 */
|
||||
|
@ -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;
|
||||
|
313
libssh/keys.c
313
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,10 +526,18 @@ 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:
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
218
libssh/wrapper.c
218
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);
|
||||
|
2
sample.c
2
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))
|
||||
|
@ -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"))
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user