1
1

Replaced calls to OpenSSL FILE-pointer functions.

Passing a FILE* argument across a DLL boundary causes problems on Windows.  Instead the keys are read into memory by libssh2 and passed to the OpenSSL functions as BIO* arguments.
Этот коммит содержится в:
Alexander Lamaison 2009-08-02 23:20:20 +01:00
родитель 6c46bb4719
Коммит 231a97a95f
3 изменённых файлов: 93 добавлений и 17 удалений

8
NEWS
Просмотреть файл

@ -1,3 +1,11 @@
* (August 02 2009) Alexander Lamaison:
- changed _libssh2_rsa_new_private and _libssh2_rsa_new_private so that they
no longer use the OpenSSL functions that take a FILE* argument. Passing
CRT-created objects across a DLL boundary causes crashes on Windows of the
DLL and the client aren't linked to the exact same verison of the CRT. Now
we pass the keys as strings to avoid this issue.
* (May 29 2009) Daniel Stenberg:
- Updated the knownhost API and there are now 9 functions, and all of them

Просмотреть файл

@ -27,6 +27,7 @@ This release includes the following bugfixes:
o public headers includable on their own
o bad debugdump() caused SIGSEGV at times (when libssh2_trace() was used)
o possible data loss when send_existing() failed to send its buffer
o passing FILE*s across DLL boundaries (OpenSSL) caused crashes on Windows
This release would not have looked like this without help, code, reports and
advice from friends like these:

Просмотреть файл

@ -43,6 +43,9 @@
#define EVP_MAX_BLOCK_LENGTH 32
#endif
/* Ridiculously large key-file size cap (512KB) */
#define MAX_KEY_FILE_LENGTH 524288
int
_libssh2_rsa_new(libssh2_rsa_ctx ** rsa,
const unsigned char *edata,
@ -212,12 +215,80 @@ passphrase_cb(char *buf, int size, int rwflag, char *passphrase)
return passphrase_len;
}
static int
read_file_into_string(char ** key, LIBSSH2_SESSION * session, FILE * fp)
{
long size;
size_t read;
*key = NULL;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
if (size < 0) {
return -1;
}
fseek(fp, 0, SEEK_SET);
size *= sizeof(char);
if (size > MAX_KEY_FILE_LENGTH) {
return -1;
}
*key = LIBSSH2_ALLOC(session, size + 1);
if (!*key) {
return -1;
}
read = fread(*key, 1, size, fp);
if (read != size) {
LIBSSH2_FREE(session, *key);
return -1;
}
(*key)[size] = '\0';
return 0;
}
typedef void * (*pem_read_bio_func)(BIO *, void **, pem_password_cb *,
void * u);
static int
read_private_key_from_file(void ** key_ctx, LIBSSH2_SESSION * session,
pem_read_bio_func read_private_key,
FILE * fp, unsigned const char *passphrase)
{
char * key;
BIO * bp;
*key_ctx = NULL;
if(read_file_into_string(&key, session, fp)) {
return -1;
}
bp = BIO_new_mem_buf(key, -1);
if (!bp) {
LIBSSH2_FREE(session, key);
return -1;
}
*key_ctx = read_private_key(bp, NULL, (void *) passphrase_cb,
(void *) passphrase);
BIO_free(bp);
LIBSSH2_FREE(session, key);
return (*key_ctx) ? 0 : -1;
}
int
_libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
LIBSSH2_SESSION * session,
FILE * fp, unsigned const char *passphrase)
{
(void) session;
pem_read_bio_func read_rsa =
(pem_read_bio_func) &PEM_read_bio_RSAPrivateKey;
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 ($#&%#$(%$#(
@ -225,12 +296,9 @@ _libssh2_rsa_new_private(libssh2_rsa_ctx ** rsa,
*/
OpenSSL_add_all_ciphers();
}
*rsa = PEM_read_RSAPrivateKey(fp, NULL, (void *) passphrase_cb,
(void *) passphrase);
if (!*rsa) {
return -1;
}
return 0;
return read_private_key_from_file((void **) rsa, session, read_rsa, fp,
passphrase);
}
int
@ -238,7 +306,9 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
LIBSSH2_SESSION * session,
FILE * fp, unsigned const char *passphrase)
{
(void) session;
pem_read_bio_func read_dsa =
(pem_read_bio_func) &PEM_read_bio_DSAPrivateKey;
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 ($#&%#$(%$#(
@ -246,12 +316,9 @@ _libssh2_dsa_new_private(libssh2_dsa_ctx ** dsa,
*/
OpenSSL_add_all_ciphers();
}
*dsa = PEM_read_DSAPrivateKey(fp, NULL, (void *) passphrase_cb,
(void *) passphrase);
if (!*dsa) {
return -1;
}
return 0;
return read_private_key_from_file((void **) dsa, session, read_dsa, fp,
passphrase);
}
int