From af6c394785d9ca41ec34ab26a9308b8a4d2a1260 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 17 Dec 2001 23:01:39 +0000 Subject: =?UTF-8?q?G=F6tz=20Babin-Ebell's=20OpenSSL=20ENGINE=20patch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/memdebug.h | 8 ++++ lib/setup.h | 7 +-- lib/ssluse.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- lib/url.c | 70 ++++++++++++++++++++++++++++-- lib/urldata.h | 17 +++++++- 5 files changed, 220 insertions(+), 15 deletions(-) (limited to 'lib') diff --git a/lib/memdebug.h b/lib/memdebug.h index ebb240928..3c5c090f6 100644 --- a/lib/memdebug.h +++ b/lib/memdebug.h @@ -1,6 +1,14 @@ #ifdef MALLOCDEBUG +#include "setup.h" + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_SYS_SOCKET_H #include +#endif #include #ifdef HAVE_MEMORY_H #include diff --git a/lib/setup.h b/lib/setup.h index bb9fc7355..cdec0f9d6 100644 --- a/lib/setup.h +++ b/lib/setup.h @@ -34,9 +34,9 @@ #ifdef HAVE_CONFIG_H #ifdef VMS -#include "config-vms.h" +#include "../config-vms.h" #else -#include "config.h" /* the configure script results */ +#include "../config.h" /* the configure script results */ #endif #else @@ -46,13 +46,14 @@ #endif #ifdef macintosh /* hand-modified MacOS config.h! */ -#include "config-mac.h" +#include "../config-mac.h" #endif #endif #ifndef __cplusplus /* (rabe) */ typedef char bool; +#define typedef_bool #endif /* (rabe) */ #ifdef NEED_REENTRANT diff --git a/lib/ssluse.c b/lib/ssluse.c index df891e2db..55b0a2e09 100644 --- a/lib/ssluse.c +++ b/lib/ssluse.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2000, Daniel Stenberg, , et al. + * Copyright (C) 2001, Daniel Stenberg, , et al. * * In order to be useful for every potential user, curl and libcurl are * dual-licensed under the MPL and the MIT/X-derivate licenses. @@ -22,11 +22,12 @@ *****************************************************************************/ /* - * The original SSL code was written by + * The original SSL code for curl was written by * Linas Vepstas and Sampo Kellomaki */ #include "setup.h" + #include #include @@ -171,33 +172,55 @@ int random_the_seed(struct connectdata *conn) return nread; } +#ifndef SSL_FILETYPE_ENGINE +#define SSL_FILETYPE_ENGINE 42 +#endif +static int do_file_type(const char *type) +{ + if (!type || !type[0]) + return SSL_FILETYPE_PEM; + if (curl_strequal(type, "PEM")) + return SSL_FILETYPE_PEM; + if (curl_strequal(type, "DER")) + return SSL_FILETYPE_ASN1; + if (curl_strequal(type, "ENG")) + return SSL_FILETYPE_ENGINE; + return -1; +} + static int cert_stuff(struct connectdata *conn, char *cert_file, - char *key_file) + const char *cert_type, + char *key_file, + const char *key_type) { struct SessionHandle *data = conn->data; + int file_type; + if (cert_file != NULL) { SSL *ssl; X509 *x509; - if(data->set.cert_passwd) { + if(data->set.key_passwd) { #ifndef HAVE_USERDATA_IN_PWD_CALLBACK /* * If password has been given, we store that in the global * area (*shudder*) for a while: */ - strcpy(global_passwd, data->set.cert_passwd); + strcpy(global_passwd, data->set.key_passwd); #else /* * We set the password in the callback userdata */ - SSL_CTX_set_default_passwd_cb_userdata(conn->ssl.ctx, data->set.cert_passwd); + SSL_CTX_set_default_passwd_cb_userdata(conn->ssl.ctx, + data->set.key_passwd); #endif /* Set passwd callback: */ SSL_CTX_set_default_passwd_cb(conn->ssl.ctx, passwd_callback); } +#if 0 if (SSL_CTX_use_certificate_file(conn->ssl.ctx, cert_file, SSL_FILETYPE_PEM) != 1) { @@ -213,6 +236,83 @@ int cert_stuff(struct connectdata *conn, failf(data, "unable to set public key file"); return(0); } +#else + /* The '#ifdef 0' section above was removed on 17-dec-2001 */ + + file_type = do_file_type(cert_type); + + switch(file_type) { + case SSL_FILETYPE_PEM: + case SSL_FILETYPE_ASN1: + if (SSL_CTX_use_certificate_file(conn->ssl.ctx, + cert_file, + file_type) != 1) { + failf(data, "unable to set certificate file (wrong password?)"); + return 0; + } + break; + case SSL_FILETYPE_ENGINE: + failf(data, "file type ENG for certificate not implemented"); + return 0; + + default: + failf(data, "not supported file type '%s' for certificate", cert_type); + return 0; + } + + file_type = do_file_type(key_type); + + switch(file_type) { + case SSL_FILETYPE_PEM: + if (key_file == NULL) + /* cert & key can only be in PEM case in the same file */ + key_file=cert_file; + case SSL_FILETYPE_ASN1: + if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx, + key_file, + file_type) != 1) { + failf(data, "unable to set private key file\n"); + return 0; + } + break; + case SSL_FILETYPE_ENGINE: +#ifdef HAVE_OPENSSL_ENGINE_H + { /* XXXX still needs some work */ + EVP_PKEY *priv_key = NULL; + if (conn && conn->data && conn->data->engine) { + if (!key_file || !key_file[0]) { + failf(data, "no key set to load from crypto engine\n"); + return 0; + } + priv_key = ENGINE_load_private_key(conn->data->engine,key_file, + data->set.key_passwd); + if (!priv_key) { + failf(data, "failed to load private key from crypto engine\n"); + return 0; + } + if (SSL_CTX_use_PrivateKey(conn->ssl.ctx, priv_key) != 1) { + failf(data, "unable to set private key\n"); + EVP_PKEY_free(priv_key); + return 0; + } + EVP_PKEY_free(priv_key); /* we don't need the handle any more... */ + } + else { + failf(data, "crypto engine not set, can't load private key\n"); + return 0; + } + } +#else + failf(data, "file type ENG for private key not supported\n"); + return 0; +#endif + break; + default: + failf(data, "not supported file type for private key\n"); + return 0; + } + +#endif ssl=SSL_new(conn->ssl.ctx); x509=SSL_get_certificate(ssl); @@ -269,6 +369,10 @@ void Curl_SSL_init(void) init_ssl++; /* never again */ +#ifdef HAVE_ENGINE_LOAD_BUILTIN_ENGINES + ENGINE_load_builtin_engines(); +#endif + /* Lets get nice error messages */ SSL_load_error_strings(); @@ -293,6 +397,10 @@ void Curl_SSL_cleanup(void) table. */ EVP_cleanup(); +#ifdef HAVE_ENGINE_cleanup + ENGINE_cleanup(); +#endif + init_ssl=0; /* not inited any more */ } #else @@ -428,6 +536,13 @@ int Curl_SSL_Close_All(struct SessionHandle *data) /* free the cache data */ free(data->state.session); } +#ifdef HAVE_OPENSSL_ENGINE_H + if (data->engine) + { + ENGINE_free(data->engine); + data->engine = NULL; + } +#endif return 0; } @@ -569,7 +684,11 @@ Curl_SSLConnect(struct connectdata *conn) } if(data->set.cert) { - if (!cert_stuff(conn, data->set.cert, data->set.cert)) { + if (!cert_stuff(conn, + data->set.cert, + data->set.cert_type, + data->set.key, + data->set.key_type)) { /* failf() is already done in cert_stuff() */ return CURLE_SSL_CONNECT_ERROR; } diff --git a/lib/url.c b/lib/url.c index 3b5482c2b..808f9c0be 100644 --- a/lib/url.c +++ b/lib/url.c @@ -790,11 +790,75 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...) */ data->set.cert = va_arg(param, char *); break; - case CURLOPT_SSLCERTPASSWD: + case CURLOPT_SSLCERTTYPE: /* - * String that holds the SSL certificate password. + * String that holds file type of the SSL certificate to use */ - data->set.cert_passwd = va_arg(param, char *); + data->set.cert_type = va_arg(param, char *); + break; + case CURLOPT_SSLKEY: + /* + * String that holds file name of the SSL certificate to use + */ + data->set.key = va_arg(param, char *); + break; + case CURLOPT_SSLKEYTYPE: + /* + * String that holds file type of the SSL certificate to use + */ + data->set.key_type = va_arg(param, char *); + break; + case CURLOPT_SSLKEYPASSWD: + /* + * String that holds the SSL private key password. + */ + data->set.key_passwd = va_arg(param, char *); + break; + case CURLOPT_SSLENGINE: + /* + * String that holds the SSL crypto engine. + */ +#ifdef HAVE_OPENSSL_ENGINE_H + { + const char *cpTemp = va_arg(param, char *); + ENGINE *e; + if (cpTemp && cpTemp[0]) { + e = ENGINE_by_id(cpTemp); + if (e) { + if (data->engine) { + ENGINE_free(data->engine); + } + data->engine = e; + } + else { + failf(data, "SSL Engine '%s' not found", cpTemp); + return CURLE_SSL_ENGINE_NOTFOUND; + } + } + } +#else + return CURLE_SSL_ENGINE_NOTFOUND; +#endif + break; + case CURLOPT_SSLENGINE_DEFAULT: + /* + * flag to set engine as default. + */ +#ifdef HAVE_OPENSSL_ENGINE_H + if (data->engine) { + if (ENGINE_set_default(data->engine, ENGINE_METHOD_ALL) > 0) { +#ifdef DEBUG + fprintf(stderr,"set default crypto engine\n"); +#endif + } + else { +#ifdef DEBUG + failf(data, "set default crypto engine failed"); +#endif + return CURLE_SSL_ENGINE_SETFAILED; + } + } +#endif break; case CURLOPT_CRLF: /* diff --git a/lib/urldata.h b/lib/urldata.h index 3a7509dcd..23aaac379 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -58,6 +58,9 @@ #include "openssl/pem.h" #include "openssl/ssl.h" #include "openssl/err.h" +#ifdef HAVE_OPENSSL_ENGINE_H +#include +#endif #else #include "rsa.h" #include "crypto.h" @@ -111,6 +114,9 @@ enum protection_level { }; #endif +#ifndef HAVE_OPENSSL_ENGINE_H +typedef void ENGINE; +#endif /* struct for data related to SSL and SSL connections */ struct ssl_connect_data { bool use; /* use ssl encrypted communications TRUE/FALSE */ @@ -525,8 +531,12 @@ struct UserDefined { char *cookie; /* HTTP cookie string to send */ struct curl_slist *headers; /* linked list of extra headers */ struct HttpPost *httppost; /* linked list of POST data */ - char *cert; /* PEM-formatted certificate */ - char *cert_passwd; /* plain text certificate password */ + char *cert; /* certificate */ + char *cert_type; /* format for certificate (default: PEM) */ + char *key; /* private key */ + char *key_type; /* format for private key (default: PEM) */ + char *key_passwd; /* plain text private key password */ + char *crypto_engine; /* name of the crypto engine to use */ char *cookiejar; /* dump all cookies to this file */ bool crlf; /* convert crlf on ftp upload(?) */ struct curl_slist *quote; /* before the transfer */ @@ -594,6 +604,9 @@ struct SessionHandle { struct UrlState state; /* struct for fields used for state info and other dynamic purposes */ struct PureInfo info; /* stats, reports and info data */ +#ifdef USE_SSLEAY + ENGINE* engine; +#endif /* USE_SSLEAY */ }; #define LIBCURL_NAME "libcurl" -- cgit v1.2.3