diff --git a/Makefile.inc b/Makefile.inc index 6f1654b..61966bd 100644 --- a/Makefile.inc +++ b/Makefile.inc @@ -1,5 +1,7 @@ CSOURCES = channel.c comp.c crypt.c hostkey.c kex.c mac.c misc.c \ packet.c publickey.c scp.c session.c sftp.c userauth.c transport.c \ - version.c knownhost.c agent.c openssl.c libgcrypt.c pem.c keepalive.c + version.c knownhost.c agent.c openssl.c libgcrypt.c pem.c keepalive.c \ + global.c -HHEADERS = libssh2_priv.h openssl.h libgcrypt.h transport.h channel.h comp.h mac.h misc.h +HHEADERS = libssh2_priv.h openssl.h libgcrypt.h transport.h channel.h \ + comp.h mac.h misc.h diff --git a/NEWS b/NEWS index a6c8c0f..5ffbb9f 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,9 @@ The APIs are libssh2_keepalive_config, and libssh2_keepalive_send. By Simon Josefsson. + o Add global init/exit points, to do crypto initialization in one place. + The APIs are libssh2_init and libssh2_exit. By Lars Nordin. + * (February 15 2010) Daniel Stenberg: - Added 46 new man pages for public convenience macros. The man pages are just short redirects to the actual underlying function. The were all diff --git a/include/libssh2.h b/include/libssh2.h index 34a8a92..293b4a1 100644 --- a/include/libssh2.h +++ b/include/libssh2.h @@ -369,6 +369,28 @@ typedef struct _LIBSSH2_POLLFD { #define LIBSSH2_ERROR_OUT_OF_BOUNDARY -41 #define LIBSSH2_ERROR_AGENT_PROTOCOL -42 +/* Global API */ +#define LIBSSH2_INIT_NO_CRYPTO_INIT 0x0001 + +/* + * libssh2_init() + * + * Initialize the libssh2 functions. flags can be: + * 0: Normal initialize + * LIBSSH2_INIT_NO_CRYPTO_INIT: Do not initialize the crypto library (ie. + * OPENSSL_add_cipher_algoritms() for OpenSSL + * + * Returns 0 if succeeded, or a negative value for error. + */ +LIBSSH2_API int libssh2_init(int flags); + +/* + * libssh2_exit() + * + * Exit the libssh2 functions and free's all memory used internal. + */ +LIBSSH2_API void libssh2_exit(); + /* Session API */ LIBSSH2_API LIBSSH2_SESSION * libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), diff --git a/src/global.c b/src/global.c new file mode 100644 index 0000000..4ee4125 --- /dev/null +++ b/src/global.c @@ -0,0 +1,67 @@ +/* Copyright (c) 2010 Lars Nordin + * All rights reserved. + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted provided + * that the following conditions are met: + * + * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * Neither the name of the copyright holder nor the names + * of any other contributors may be used to endorse or + * promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + */ + +#include "libssh2_priv.h" + +int libssh2_initialized = 0; +int libssh2_init_flags = 0; + +LIBSSH2_API int libssh2_init(int flags) +{ + if (!(flags & LIBSSH2_INIT_NO_CRYPTO_INIT)) { + libssh2_crypto_init(); + } + + libssh2_initialized++; + libssh2_init_flags &= flags; + + return 0; +} + +LIBSSH2_API void libssh2_exit() +{ + if (libssh2_initialized == 0) + return; + + if (!(libssh2_init_flags & LIBSSH2_INIT_NO_CRYPTO_INIT)) { + libssh2_crypto_exit(); + } + + libssh2_initialized--; + + return; +} diff --git a/src/libgcrypt.h b/src/libgcrypt.h index b972c35..2a48270 100644 --- a/src/libgcrypt.h +++ b/src/libgcrypt.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Simon Josefsson + * Copyright (C) 2008, 2009, 2010 Simon Josefsson * Copyright (C) 2006, 2007, The Written Word, Inc. * All rights reserved. * @@ -93,6 +93,7 @@ #define libssh2_hmac_cleanup(ctx) gcry_md_close (*ctx); #define libssh2_crypto_init() gcry_control (GCRYCTL_DISABLE_SECMEM) +#define libssh2_crypto_exit() #define libssh2_rsa_ctx struct gcry_sexp diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h index 86aeed8..0c2145c 100644 --- a/src/libssh2_priv.h +++ b/src/libssh2_priv.h @@ -1247,5 +1247,6 @@ int _libssh2_pem_decode_integer(unsigned char **data, unsigned int *datalen, #define ARRAY_SIZE(a) (sizeof ((a)) / sizeof ((a)[0])) +extern int libssh2_initialized; #endif /* LIBSSH2_H */ diff --git a/src/openssl.c b/src/openssl.c index 1af3bcd..9fbba25 100644 --- a/src/openssl.c +++ b/src/openssl.c @@ -105,7 +105,7 @@ _libssh2_rsa_sha1_verify(libssh2_rsa_ctx * rsactx, unsigned char hash[SHA_DIGEST_LENGTH]; int ret; - SHA1(m, m_len, hash); + libssh2_sha1(m, m_len, hash); ret = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH, (unsigned char *) sig, sig_len, rsactx); return (ret == 1) ? 0 : -1; @@ -358,13 +358,8 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa, (pem_read_bio_func) &PEM_read_bio_RSAPrivateKey; (void) session; - if (!EVP_get_cipherbyname("des")) { -/* If this cipher isn't loaded it's a pretty good indication that none are. - * I have *NO DOUBT* that there's a better way to deal with this ($#&%#$(%$#( - * Someone buy me an OpenSSL manual and I'll read up on it. - */ - OpenSSL_add_all_ciphers(); - } + if (!libssh2_initialized) + libssh2_init(0); return read_private_key_from_file((void **) rsa, read_rsa, filename, passphrase); @@ -380,13 +375,8 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa, (pem_read_bio_func) &PEM_read_bio_DSAPrivateKey; (void) session; - if (!EVP_get_cipherbyname("des")) { -/* If this cipher isn't loaded it's a pretty good indication that none are. - * I have *NO DOUBT* that there's a better way to deal with this ($#&%#$(%$#( - * Someone buy me an OpenSSL manual and I'll read up on it. - */ - OpenSSL_add_all_ciphers(); - } + if (!libssh2_initialized) + libssh2_init(0); return read_private_key_from_file((void **) dsa, read_dsa, filename, passphrase); @@ -461,4 +451,26 @@ _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx, } #endif /* LIBSSH_DSA */ +void +libssh2_sha1(const unsigned char *message, unsigned long len, + unsigned char *out) +{ + EVP_MD_CTX ctx; + + EVP_DigestInit(&ctx, EVP_get_digestbyname("sha1")); + EVP_DigestUpdate(&ctx, message, len); + EVP_DigestFinal(&ctx, out, NULL); +} + +void +libssh2_md5(const unsigned char *message, unsigned long len, + unsigned char *out) +{ + EVP_MD_CTX ctx; + + EVP_DigestInit(&ctx, EVP_get_digestbyname("md5")); + EVP_DigestUpdate(&ctx, message, len); + EVP_DigestFinal(&ctx, out, NULL); +} + #endif /* !LIBSSH2_LIBGCRYPT */ diff --git a/src/openssl.h b/src/openssl.h index 3e0512b..ed62d23 100644 --- a/src/openssl.h +++ b/src/openssl.h @@ -106,17 +106,17 @@ #define libssh2_random(buf, len) RAND_bytes ((buf), (len)) -#define libssh2_sha1_ctx SHA_CTX -#define libssh2_sha1_init(ctx) SHA1_Init(ctx) -#define libssh2_sha1_update(ctx, data, len) SHA1_Update(&(ctx), data, len) -#define libssh2_sha1_final(ctx, out) SHA1_Final(out, &(ctx)) -#define libssh2_sha1(message, len, out) SHA1(message, len, out) +#define libssh2_sha1_ctx EVP_MD_CTX +#define libssh2_sha1_init(ctx) EVP_DigestInit(ctx, EVP_get_digestbyname("sha1")) +#define libssh2_sha1_update(ctx, data, len) EVP_DigestUpdate(&(ctx), data, len) +#define libssh2_sha1_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL) +void libssh2_sha1(const unsigned char *message, unsigned long len, unsigned char *out); -#define libssh2_md5_ctx MD5_CTX -#define libssh2_md5_init(ctx) MD5_Init(ctx) -#define libssh2_md5_update(ctx, data, len) MD5_Update(&(ctx), data, len) -#define libssh2_md5_final(ctx, out) MD5_Final(out, &(ctx)) -#define libssh2_md5(message, len, out) MD5(message, len, out) +#define libssh2_md5_ctx EVP_MD_CTX +#define libssh2_md5_init(ctx) EVP_DigestInit(ctx, EVP_get_digestbyname("md5")) +#define libssh2_md5_update(ctx, data, len) EVP_DigestUpdate(&(ctx), data, len) +#define libssh2_md5_final(ctx, out) EVP_DigestFinal(&(ctx), out, NULL) +void libssh2_md5(const unsigned char *message, unsigned long len, unsigned char *out); #define libssh2_hmac_ctx HMAC_CTX #define libssh2_hmac_sha1_init(ctx, key, keylen) \ @@ -130,7 +130,8 @@ #define libssh2_hmac_final(ctx, data) HMAC_Final(&(ctx), data, NULL) #define libssh2_hmac_cleanup(ctx) HMAC_cleanup(ctx) -#define libssh2_crypto_init() +#define libssh2_crypto_init() OpenSSL_add_all_algorithms() +#define libssh2_crypto_exit() #define libssh2_rsa_ctx RSA diff --git a/src/session.c b/src/session.c index f32924b..f280954 100644 --- a/src/session.c +++ b/src/session.c @@ -457,7 +457,8 @@ libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), session->api_block_mode = 1; /* blocking API by default */ _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "New session resource allocated"); - libssh2_crypto_init(); + if (!libssh2_initialized) + libssh2_init(0); } return session; }