aboutsummaryrefslogtreecommitdiff
path: root/mysql/extra/yassl/src/ssl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mysql/extra/yassl/src/ssl.cpp')
-rw-r--r--mysql/extra/yassl/src/ssl.cpp1883
1 files changed, 1883 insertions, 0 deletions
diff --git a/mysql/extra/yassl/src/ssl.cpp b/mysql/extra/yassl/src/ssl.cpp
new file mode 100644
index 0000000..39244a0
--- /dev/null
+++ b/mysql/extra/yassl/src/ssl.cpp
@@ -0,0 +1,1883 @@
+/*
+ Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ MA 02110-1301 USA.
+*/
+
+/* SSL source implements all openssl compatibility API functions
+ *
+ * TODO: notes are mostly api additions to allow compilation with mysql
+ * they don't affect normal modes but should be provided for completeness
+
+ * stunnel functions at end of file
+ */
+
+
+
+/* see man pages for function descriptions */
+
+#include "runtime.hpp"
+#include "openssl/ssl.h"
+#include "handshake.hpp"
+#include "yassl_int.hpp"
+#include "md5.hpp" // for TaoCrypt MD5 size assert
+#include "md4.hpp" // for TaoCrypt MD4 size assert
+#include "file.hpp" // for TaoCrypt Source
+#include "coding.hpp" // HexDecoder
+#include "helpers.hpp" // for placement new hack
+#include "rsa.hpp" // for TaoCrypt RSA key decode
+#include "dsa.hpp" // for TaoCrypt DSA key decode
+#include <stdio.h>
+
+#ifdef _WIN32
+ #include <windows.h> // FindFirstFile etc..
+#else
+ #include <sys/types.h> // file helper
+ #include <sys/stat.h> // stat
+ #include <dirent.h> // opendir
+#endif
+
+
+namespace yaSSL {
+
+
+
+int read_file(SSL_CTX* ctx, const char* file, int format, CertType type)
+{
+ int ret = SSL_SUCCESS;
+
+ if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM)
+ return SSL_BAD_FILETYPE;
+
+ if (file == NULL || !file[0])
+ return SSL_BAD_FILE;
+
+ FILE* input = fopen(file, "rb");
+ if (!input)
+ return SSL_BAD_FILE;
+
+ if (type == CA) {
+ // may have a bunch of CAs
+ x509* ptr;
+ while ( (ptr = PemToDer(input, Cert)) )
+ ctx->AddCA(ptr);
+
+ if (!feof(input)) {
+ fclose(input);
+ return SSL_BAD_FILE;
+ }
+ }
+ else {
+ x509*& x = (type == Cert) ? ctx->certificate_ : ctx->privateKey_;
+
+ if (format == SSL_FILETYPE_ASN1) {
+ fseek(input, 0, SEEK_END);
+ long sz = ftell(input);
+ rewind(input);
+ x = NEW_YS x509(sz); // takes ownership
+ size_t bytes = fread(x->use_buffer(), sz, 1, input);
+ if (bytes != 1) {
+ fclose(input);
+ return SSL_BAD_FILE;
+ }
+ }
+ else {
+ EncryptedInfo info;
+ x = PemToDer(input, type, &info);
+ if (!x) {
+ fclose(input);
+ return SSL_BAD_FILE;
+ }
+ if (info.set) {
+ // decrypt
+ char password[80];
+ pem_password_cb cb = ctx->GetPasswordCb();
+ if (!cb) {
+ fclose(input);
+ return SSL_BAD_FILE;
+ }
+ int passwordSz = cb(password, sizeof(password), 0,
+ ctx->GetUserData());
+ byte key[AES_256_KEY_SZ]; // max sizes
+ byte iv[AES_IV_SZ];
+
+ // use file's salt for key derivation, but not real iv
+ TaoCrypt::Source source(info.iv, info.ivSz);
+ TaoCrypt::HexDecoder dec(source);
+ memcpy(info.iv, source.get_buffer(), min((uint)sizeof(info.iv),
+ source.size()));
+ EVP_BytesToKey(info.name, "MD5", info.iv, (byte*)password,
+ passwordSz, 1, key, iv);
+
+ mySTL::auto_ptr<BulkCipher> cipher;
+ if (strncmp(info.name, "DES-CBC", 7) == 0)
+ cipher.reset(NEW_YS DES);
+ else if (strncmp(info.name, "DES-EDE3-CBC", 13) == 0)
+ cipher.reset(NEW_YS DES_EDE);
+ else if (strncmp(info.name, "AES-128-CBC", 13) == 0)
+ cipher.reset(NEW_YS AES(AES_128_KEY_SZ));
+ else if (strncmp(info.name, "AES-192-CBC", 13) == 0)
+ cipher.reset(NEW_YS AES(AES_192_KEY_SZ));
+ else if (strncmp(info.name, "AES-256-CBC", 13) == 0)
+ cipher.reset(NEW_YS AES(AES_256_KEY_SZ));
+ else {
+ fclose(input);
+ return SSL_BAD_FILE;
+ }
+ cipher->set_decryptKey(key, info.iv);
+ mySTL::auto_ptr<x509> newx(NEW_YS x509(x->get_length()));
+ cipher->decrypt(newx->use_buffer(), x->get_buffer(),
+ x->get_length());
+ ysDelete(x);
+ x = newx.release();
+ }
+ }
+ }
+
+ if (type == PrivateKey && ctx->privateKey_) {
+ // see if key is valid early
+ TaoCrypt::Source rsaSource(ctx->privateKey_->get_buffer(),
+ ctx->privateKey_->get_length());
+ TaoCrypt::RSA_PrivateKey rsaKey;
+ rsaKey.Initialize(rsaSource);
+
+ if (rsaSource.GetError().What()) {
+ // rsa failed see if DSA works
+
+ TaoCrypt::Source dsaSource(ctx->privateKey_->get_buffer(),
+ ctx->privateKey_->get_length());
+ TaoCrypt::DSA_PrivateKey dsaKey;
+ dsaKey.Initialize(dsaSource);
+
+ if (dsaSource.GetError().What()) {
+ // neither worked
+ ret = SSL_FAILURE;
+ }
+ }
+ }
+
+ fclose(input);
+ return ret;
+}
+
+
+extern "C" {
+
+
+SSL_METHOD* SSLv3_method()
+{
+ return SSLv3_client_method();
+}
+
+
+SSL_METHOD* SSLv3_server_method()
+{
+ return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,0));
+}
+
+
+SSL_METHOD* SSLv3_client_method()
+{
+ return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,0));
+}
+
+
+SSL_METHOD* TLSv1_server_method()
+{
+ return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,1));
+}
+
+
+SSL_METHOD* TLSv1_client_method()
+{
+ return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,1));
+}
+
+
+SSL_METHOD* TLSv1_1_server_method()
+{
+ return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,2));
+}
+
+
+SSL_METHOD* TLSv1_1_client_method()
+{
+ return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,2));
+}
+
+
+SSL_METHOD* SSLv23_server_method()
+{
+ // compatibility only, no version 2 support, but does SSL 3 and TLS 1
+ return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,2), true);
+}
+
+
+SSL_METHOD* SSLv23_client_method()
+{
+ // compatibility only, no version 2 support, but does SSL 3 and TLS 1
+ // though it sends TLS1 hello not SSLv2 so SSLv3 only servers will decline
+ // TODO: maybe add support to send SSLv2 hello ???
+ return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,2), true);
+}
+
+
+SSL_CTX* SSL_CTX_new(SSL_METHOD* method)
+{
+ return NEW_YS SSL_CTX(method);
+}
+
+
+void SSL_CTX_free(SSL_CTX* ctx)
+{
+ ysDelete(ctx);
+}
+
+
+SSL* SSL_new(SSL_CTX* ctx)
+{
+ return NEW_YS SSL(ctx);
+}
+
+
+void SSL_free(SSL* ssl)
+{
+ ysDelete(ssl);
+}
+
+
+int SSL_set_fd(SSL* ssl, YASSL_SOCKET_T fd)
+{
+ ssl->useSocket().set_fd(fd);
+ return SSL_SUCCESS;
+}
+
+
+YASSL_SOCKET_T SSL_get_fd(const SSL* ssl)
+{
+ return ssl->getSocket().get_fd();
+}
+
+
+// if you get an error from connect see note at top of README
+int SSL_connect(SSL* ssl)
+{
+ if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ))
+ ssl->SetError(no_error);
+
+ if (ssl->GetError() == YasslError(SSL_ERROR_WANT_WRITE)) {
+
+ ssl->SetError(no_error);
+ ssl->SendWriteBuffered();
+ if (!ssl->GetError())
+ ssl->useStates().UseConnect() =
+ ConnectState(ssl->getStates().GetConnect() + 1);
+ }
+
+ ClientState neededState;
+
+ switch (ssl->getStates().GetConnect()) {
+
+ case CONNECT_BEGIN :
+ sendClientHello(*ssl);
+ if (!ssl->GetError())
+ ssl->useStates().UseConnect() = CLIENT_HELLO_SENT;
+
+ case CLIENT_HELLO_SENT :
+ neededState = ssl->getSecurity().get_resuming() ?
+ serverFinishedComplete : serverHelloDoneComplete;
+ while (ssl->getStates().getClient() < neededState) {
+ if (ssl->GetError()) break;
+ processReply(*ssl);
+ // if resumption failed, reset needed state
+ if (neededState == serverFinishedComplete)
+ if (!ssl->getSecurity().get_resuming())
+ neededState = serverHelloDoneComplete;
+ }
+ if (!ssl->GetError())
+ ssl->useStates().UseConnect() = FIRST_REPLY_DONE;
+
+ case FIRST_REPLY_DONE :
+ if(ssl->getCrypto().get_certManager().sendVerify())
+ sendCertificate(*ssl);
+
+ if (!ssl->getSecurity().get_resuming())
+ sendClientKeyExchange(*ssl);
+
+ if(ssl->getCrypto().get_certManager().sendVerify())
+ sendCertificateVerify(*ssl);
+
+ sendChangeCipher(*ssl);
+ sendFinished(*ssl, client_end);
+ ssl->flushBuffer();
+
+ if (!ssl->GetError())
+ ssl->useStates().UseConnect() = FINISHED_DONE;
+
+ case FINISHED_DONE :
+ if (!ssl->getSecurity().get_resuming())
+ while (ssl->getStates().getClient() < serverFinishedComplete) {
+ if (ssl->GetError()) break;
+ processReply(*ssl);
+ }
+ if (!ssl->GetError())
+ ssl->useStates().UseConnect() = SECOND_REPLY_DONE;
+
+ case SECOND_REPLY_DONE :
+ ssl->verifyState(serverFinishedComplete);
+ ssl->useLog().ShowTCP(ssl->getSocket().get_fd());
+
+ if (ssl->GetError()) {
+ GetErrors().Add(ssl->GetError());
+ return SSL_FATAL_ERROR;
+ }
+ return SSL_SUCCESS;
+
+ default :
+ return SSL_FATAL_ERROR; // unkown state
+ }
+}
+
+
+int SSL_write(SSL* ssl, const void* buffer, int sz)
+{
+ return sendData(*ssl, buffer, sz);
+}
+
+
+int SSL_read(SSL* ssl, void* buffer, int sz)
+{
+ Data data(min(sz, MAX_RECORD_SIZE), static_cast<opaque*>(buffer));
+ return receiveData(*ssl, data);
+}
+
+
+int SSL_accept(SSL* ssl)
+{
+ if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ))
+ ssl->SetError(no_error);
+
+ if (ssl->GetError() == YasslError(SSL_ERROR_WANT_WRITE)) {
+
+ ssl->SetError(no_error);
+ ssl->SendWriteBuffered();
+ if (!ssl->GetError())
+ ssl->useStates().UseAccept() =
+ AcceptState(ssl->getStates().GetAccept() + 1);
+ }
+
+ switch (ssl->getStates().GetAccept()) {
+
+ case ACCEPT_BEGIN :
+ processReply(*ssl);
+ if (!ssl->GetError())
+ ssl->useStates().UseAccept() = ACCEPT_FIRST_REPLY_DONE;
+
+ case ACCEPT_FIRST_REPLY_DONE :
+ sendServerHello(*ssl);
+
+ if (!ssl->getSecurity().get_resuming()) {
+ sendCertificate(*ssl);
+
+ if (ssl->getSecurity().get_connection().send_server_key_)
+ sendServerKeyExchange(*ssl);
+
+ if(ssl->getCrypto().get_certManager().verifyPeer())
+ sendCertificateRequest(*ssl);
+
+ sendServerHelloDone(*ssl);
+ ssl->flushBuffer();
+ }
+
+ if (!ssl->GetError())
+ ssl->useStates().UseAccept() = SERVER_HELLO_DONE;
+
+ case SERVER_HELLO_DONE :
+ if (!ssl->getSecurity().get_resuming()) {
+ while (ssl->getStates().getServer() < clientFinishedComplete) {
+ if (ssl->GetError()) break;
+ processReply(*ssl);
+ }
+ }
+ if (!ssl->GetError())
+ ssl->useStates().UseAccept() = ACCEPT_SECOND_REPLY_DONE;
+
+ case ACCEPT_SECOND_REPLY_DONE :
+ sendChangeCipher(*ssl);
+ sendFinished(*ssl, server_end);
+ ssl->flushBuffer();
+
+ if (!ssl->GetError())
+ ssl->useStates().UseAccept() = ACCEPT_FINISHED_DONE;
+
+ case ACCEPT_FINISHED_DONE :
+ if (ssl->getSecurity().get_resuming()) {
+ while (ssl->getStates().getServer() < clientFinishedComplete) {
+ if (ssl->GetError()) break;
+ processReply(*ssl);
+ }
+ }
+ if (!ssl->GetError())
+ ssl->useStates().UseAccept() = ACCEPT_THIRD_REPLY_DONE;
+
+ case ACCEPT_THIRD_REPLY_DONE :
+ ssl->useLog().ShowTCP(ssl->getSocket().get_fd());
+
+ if (ssl->GetError()) {
+ GetErrors().Add(ssl->GetError());
+ return SSL_FATAL_ERROR;
+ }
+ return SSL_SUCCESS;
+
+ default:
+ return SSL_FATAL_ERROR; // unknown state
+ }
+}
+
+
+int SSL_do_handshake(SSL* ssl)
+{
+ if (ssl->getSecurity().get_parms().entity_ == client_end)
+ return SSL_connect(ssl);
+ else
+ return SSL_accept(ssl);
+}
+
+
+int SSL_clear(SSL* ssl)
+{
+ GetErrors().Remove();
+
+ return SSL_SUCCESS;
+}
+
+
+int SSL_shutdown(SSL* ssl)
+{
+ if (!ssl->GetQuietShutdown()) {
+ Alert alert(warning, close_notify);
+ sendAlert(*ssl, alert);
+ }
+ ssl->useLog().ShowTCP(ssl->getSocket().get_fd(), true);
+
+ GetErrors().Remove();
+
+ return SSL_SUCCESS;
+}
+
+
+void SSL_set_quiet_shutdown(SSL *ssl,int mode)
+{
+ ssl->SetQuietShutdown(mode != 0);
+}
+
+
+int SSL_get_quiet_shutdown(SSL *ssl)
+{
+ return ssl->GetQuietShutdown();
+}
+
+
+/* on by default but allow user to turn off */
+long SSL_CTX_set_session_cache_mode(SSL_CTX* ctx, long mode)
+{
+ if (mode == SSL_SESS_CACHE_OFF)
+ ctx->SetSessionCacheOff();
+
+ if (mode == SSL_SESS_CACHE_NO_AUTO_CLEAR)
+ ctx->SetSessionCacheFlushOff();
+
+ return SSL_SUCCESS;
+}
+
+
+SSL_SESSION* SSL_get_session(SSL* ssl)
+{
+ if (ssl->getSecurity().GetContext()->GetSessionCacheOff())
+ return 0;
+
+ return GetSessions().lookup(
+ ssl->getSecurity().get_connection().sessionID_);
+}
+
+
+int SSL_set_session(SSL* ssl, SSL_SESSION* session)
+{
+ if (ssl->getSecurity().GetContext()->GetSessionCacheOff())
+ return SSL_FAILURE;
+
+ ssl->set_session(session);
+ return SSL_SUCCESS;
+}
+
+
+int SSL_session_reused(SSL* ssl)
+{
+ return ssl->getSecurity().get_resuming();
+}
+
+
+long SSL_SESSION_set_timeout(SSL_SESSION* sess, long t)
+{
+ if (!sess)
+ return SSL_ERROR_NONE;
+
+ sess->SetTimeOut(t);
+ return SSL_SUCCESS;
+}
+
+
+long SSL_get_default_timeout(SSL* /*ssl*/)
+{
+ return DEFAULT_TIMEOUT;
+}
+
+
+void SSL_flush_sessions(SSL_CTX *ctx, long /* tm */)
+{
+ if (ctx->GetSessionCacheOff())
+ return;
+
+ GetSessions().Flush();
+}
+
+
+const char* SSL_get_cipher_name(SSL* ssl)
+{
+ return SSL_get_cipher(ssl);
+}
+
+
+const char* SSL_get_cipher(SSL* ssl)
+{
+ return ssl->getSecurity().get_parms().cipher_name_;
+}
+
+
+// SSLv2 only, not implemented
+char* SSL_get_shared_ciphers(SSL* /*ssl*/, char* buf, int len)
+{
+ return strncpy(buf, "Not Implemented, SSLv2 only", len);
+}
+
+
+const char* SSL_get_cipher_list(SSL* ssl, int priority)
+{
+ if (priority < 0 || priority >= MAX_CIPHERS)
+ return 0;
+
+ if (ssl->getSecurity().get_parms().cipher_list_[priority][0])
+ return ssl->getSecurity().get_parms().cipher_list_[priority];
+
+ return 0;
+}
+
+
+int SSL_CTX_set_cipher_list(SSL_CTX* ctx, const char* list)
+{
+ if (ctx->SetCipherList(list))
+ return SSL_SUCCESS;
+ else
+ return SSL_FAILURE;
+}
+
+
+const char* SSL_get_version(SSL* ssl)
+{
+ static const char* version3 = "SSLv3";
+ static const char* version31 = "TLSv1";
+ static const char* version32 = "TLSv1.1";
+
+ if (ssl->isTLSv1_1())
+ return version32;
+ else if(ssl->isTLS())
+ return version31;
+ else
+ return version3;
+}
+
+const char* SSLeay_version(int)
+{
+ static const char* version = "SSLeay yaSSL compatibility";
+ return version;
+}
+
+
+int SSL_get_error(SSL* ssl, int /*previous*/)
+{
+ return ssl->getStates().What();
+}
+
+
+
+/* turn on yaSSL zlib compression
+ returns 0 for success, else error (not built in)
+ only need to turn on for client, becuase server on by default if built in
+ but calling for server will tell you whether it's available or not
+*/
+int SSL_set_compression(SSL* ssl) /* Chad didn't rename to ya~ because it is prob. bug. */
+{
+ return ssl->SetCompression();
+}
+
+
+
+X509* X509_Copy(X509 *x)
+{
+ if (x == 0) return NULL;
+
+ X509_NAME* issuer = x->GetIssuer();
+ X509_NAME* subject = x->GetSubject();
+ ASN1_TIME* before = x->GetBefore();
+ ASN1_TIME* after = x->GetAfter();
+
+ X509 *newX509 = NEW_YS X509(issuer->GetName(), issuer->GetLength(),
+ subject->GetName(), subject->GetLength(),
+ before, after,
+ issuer->GetCnPosition(), issuer->GetCnLength(),
+ subject->GetCnPosition(), subject->GetCnLength());
+
+ return newX509;
+}
+
+X509* SSL_get_peer_certificate(SSL* ssl)
+{
+ return X509_Copy(ssl->getCrypto().get_certManager().get_peerX509());
+}
+
+
+void X509_free(X509* x)
+{
+ ysDelete(x);
+}
+
+
+X509* X509_STORE_CTX_get_current_cert(X509_STORE_CTX* ctx)
+{
+ return ctx->current_cert;
+}
+
+
+int X509_STORE_CTX_get_error(X509_STORE_CTX* ctx)
+{
+ return ctx->error;
+}
+
+
+int X509_STORE_CTX_get_error_depth(X509_STORE_CTX* ctx)
+{
+ return ctx->error_depth;
+}
+
+X509* PEM_read_X509(FILE *fp, X509 *x,
+ pem_password_cb cb,
+ void *u)
+{
+ if (fp == NULL)
+ return NULL;
+
+ // Get x509 handle and encryption information
+ x509* ptr = PemToDer(fp, Cert);
+ if (!ptr)
+ return NULL;
+
+ // Now decode x509 object.
+ TaoCrypt::SignerList signers;
+ TaoCrypt::Source source(ptr->get_buffer(), ptr->get_length());
+ TaoCrypt::CertDecoder cert(source, true, &signers, true, TaoCrypt::CertDecoder::CA);
+
+ if (cert.GetError().What()) {
+ ysDelete(ptr);
+ return NULL;
+ }
+
+ // Ok. Now create X509 object.
+ size_t iSz = strlen(cert.GetIssuer()) + 1;
+ size_t sSz = strlen(cert.GetCommonName()) + 1;
+ ASN1_STRING beforeDate, afterDate;
+ beforeDate.data = (unsigned char *) cert.GetBeforeDate();
+ beforeDate.type = cert.GetBeforeDateType();
+ beforeDate.length = strlen((char *) beforeDate.data) + 1;
+ afterDate.data = (unsigned char *) cert.GetAfterDate();
+ afterDate.type = cert.GetAfterDateType();
+ afterDate.length = strlen((char *) afterDate.data) + 1;
+
+ X509 *thisX509 = NEW_YS X509(cert.GetIssuer(), iSz, cert.GetCommonName(),
+ sSz, &beforeDate, &afterDate,
+ cert.GetIssuerCnStart(), cert.GetIssuerCnLength(),
+ cert.GetSubjectCnStart(), cert.GetSubjectCnLength());
+
+
+ ysDelete(ptr);
+ return thisX509;
+}
+
+// copy name into buffer, at most sz bytes, if buffer is null
+// will malloc buffer, caller responsible for freeing
+char* X509_NAME_oneline(X509_NAME* name, char* buffer, int sz)
+{
+ if (!name->GetName()) return buffer;
+
+ int len = (int)strlen(name->GetName()) + 1;
+ int copySz = min(len, sz);
+
+ if (!buffer) {
+ buffer = (char*)malloc(len);
+ if (!buffer) return buffer;
+ copySz = len;
+ }
+
+ if (copySz == 0)
+ return buffer;
+
+ memcpy(buffer, name->GetName(), copySz - 1);
+ buffer[copySz - 1] = 0;
+
+ return buffer;
+}
+
+
+X509_NAME* X509_get_issuer_name(X509* x)
+{
+ return x->GetIssuer();
+}
+
+
+X509_NAME* X509_get_subject_name(X509* x)
+{
+ return x->GetSubject();
+}
+
+
+void SSL_load_error_strings() // compatibility only
+{}
+
+
+void SSL_set_connect_state(SSL*)
+{
+ // already a client by default
+}
+
+
+void SSL_set_accept_state(SSL* ssl)
+{
+ ssl->useSecurity().use_parms().entity_ = server_end;
+}
+
+
+long SSL_get_verify_result(SSL*)
+{
+ // won't get here if not OK
+ return X509_V_OK;
+}
+
+
+long SSL_CTX_sess_set_cache_size(SSL_CTX* /*ctx*/, long /*sz*/)
+{
+ // unlimited size, can't set for now
+ return 0;
+}
+
+
+long SSL_CTX_get_session_cache_mode(SSL_CTX*)
+{
+ // always 0, unlimited size for now
+ return 0;
+}
+
+
+long SSL_CTX_set_tmp_dh(SSL_CTX* ctx, DH* dh)
+{
+ if (ctx->SetDH(*dh))
+ return SSL_SUCCESS;
+ else
+ return SSL_FAILURE;
+}
+
+
+int SSL_CTX_use_certificate_file(SSL_CTX* ctx, const char* file, int format)
+{
+ return read_file(ctx, file, format, Cert);
+}
+
+
+int SSL_CTX_use_PrivateKey_file(SSL_CTX* ctx, const char* file, int format)
+{
+ return read_file(ctx, file, format, PrivateKey);
+}
+
+
+void SSL_CTX_set_verify(SSL_CTX* ctx, int mode, VerifyCallback vc)
+{
+ if (mode & SSL_VERIFY_PEER)
+ ctx->setVerifyPeer();
+
+ if (mode == SSL_VERIFY_NONE)
+ ctx->setVerifyNone();
+
+ if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
+ ctx->setFailNoCert();
+
+ ctx->setVerifyCallback(vc);
+}
+
+
+int SSL_CTX_load_verify_locations(SSL_CTX* ctx, const char* file,
+ const char* path)
+{
+ int ret = SSL_FAILURE;
+ const int HALF_PATH = 128;
+
+ if (file) ret = read_file(ctx, file, SSL_FILETYPE_PEM, CA);
+
+ if (ret == SSL_SUCCESS && path) {
+ // call read_file for each reqular file in path
+#ifdef _WIN32
+
+ WIN32_FIND_DATA FindFileData;
+ HANDLE hFind;
+
+ const int DELIMITER_SZ = 2;
+ const int DELIMITER_STAR_SZ = 3;
+ int pathSz = (int)strlen(path);
+ int nameSz = pathSz + DELIMITER_STAR_SZ + 1; // plus 1 for terminator
+ char* name = NEW_YS char[nameSz]; // directory specification
+ memset(name, 0, nameSz);
+ strncpy(name, path, nameSz - DELIMITER_STAR_SZ - 1);
+ strncat(name, "\\*", DELIMITER_STAR_SZ);
+
+ hFind = FindFirstFile(name, &FindFileData);
+ if (hFind == INVALID_HANDLE_VALUE) {
+ ysArrayDelete(name);
+ return SSL_BAD_PATH;
+ }
+
+ do {
+ if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ int curSz = (int)strlen(FindFileData.cFileName);
+ if (pathSz + curSz + DELIMITER_SZ + 1 > nameSz) {
+ ysArrayDelete(name);
+ // plus 1 for terminator
+ nameSz = pathSz + curSz + DELIMITER_SZ + 1;
+ name = NEW_YS char[nameSz];
+ }
+ memset(name, 0, nameSz);
+ strncpy(name, path, nameSz - curSz - DELIMITER_SZ - 1);
+ strncat(name, "\\", DELIMITER_SZ);
+ strncat(name, FindFileData.cFileName,
+ nameSz - pathSz - DELIMITER_SZ - 1);
+ ret = read_file(ctx, name, SSL_FILETYPE_PEM, CA);
+ }
+ } while (ret == SSL_SUCCESS && FindNextFile(hFind, &FindFileData));
+
+ ysArrayDelete(name);
+ FindClose(hFind);
+
+#else // _WIN32
+ DIR* dir = opendir(path);
+ if (!dir) return SSL_BAD_PATH;
+
+ struct dirent* entry;
+ struct stat buf;
+ const int DELIMITER_SZ = 1;
+ int pathSz = (int)strlen(path);
+ int nameSz = pathSz + DELIMITER_SZ + 1; //plus 1 for null terminator
+ char* name = NEW_YS char[nameSz]; // directory specification
+
+ while (ret == SSL_SUCCESS && (entry = readdir(dir))) {
+ int curSz = (int)strlen(entry->d_name);
+ if (pathSz + curSz + DELIMITER_SZ + 1 > nameSz) {
+ ysArrayDelete(name);
+ nameSz = pathSz + DELIMITER_SZ + curSz + 1;
+ name = NEW_YS char[nameSz];
+ }
+ memset(name, 0, nameSz);
+ strncpy(name, path, nameSz - curSz - 1);
+ strncat(name, "/", DELIMITER_SZ);
+ strncat(name, entry->d_name, nameSz - pathSz - DELIMITER_SZ - 1);
+
+ if (stat(name, &buf) < 0) {
+ ysArrayDelete(name);
+ closedir(dir);
+ return SSL_BAD_STAT;
+ }
+
+ if (S_ISREG(buf.st_mode))
+ ret = read_file(ctx, name, SSL_FILETYPE_PEM, CA);
+ }
+
+ ysArrayDelete(name);
+ closedir(dir);
+
+#endif
+ }
+
+ return ret;
+}
+
+
+int SSL_CTX_set_default_verify_paths(SSL_CTX* /*ctx*/)
+{
+ // TODO: figure out way to set/store default path, then call load_verify
+ return SSL_NOT_IMPLEMENTED;
+}
+
+
+int SSL_CTX_set_session_id_context(SSL_CTX*, const unsigned char*,
+ unsigned int)
+{
+ // No application specific context needed for yaSSL
+ return SSL_SUCCESS;
+}
+
+
+int SSL_CTX_check_private_key(SSL_CTX* /*ctx*/)
+{
+ // TODO: check private against public for RSA match
+ return SSL_NOT_IMPLEMENTED;
+}
+
+
+// TODO: all session stats
+long SSL_CTX_sess_accept(SSL_CTX* ctx)
+{
+ return ctx->GetStats().accept_;
+}
+
+
+long SSL_CTX_sess_connect(SSL_CTX* ctx)
+{
+ return ctx->GetStats().connect_;
+}
+
+
+long SSL_CTX_sess_accept_good(SSL_CTX* ctx)
+{
+ return ctx->GetStats().acceptGood_;
+}
+
+
+long SSL_CTX_sess_connect_good(SSL_CTX* ctx)
+{
+ return ctx->GetStats().connectGood_;
+}
+
+
+long SSL_CTX_sess_accept_renegotiate(SSL_CTX* ctx)
+{
+ return ctx->GetStats().acceptRenegotiate_;
+}
+
+
+long SSL_CTX_sess_connect_renegotiate(SSL_CTX* ctx)
+{
+ return ctx->GetStats().connectRenegotiate_;
+}
+
+
+long SSL_CTX_sess_hits(SSL_CTX* ctx)
+{
+ return ctx->GetStats().hits_;
+}
+
+
+long SSL_CTX_sess_cb_hits(SSL_CTX* ctx)
+{
+ return ctx->GetStats().cbHits_;
+}
+
+
+long SSL_CTX_sess_cache_full(SSL_CTX* ctx)
+{
+ return ctx->GetStats().cacheFull_;
+}
+
+
+long SSL_CTX_sess_misses(SSL_CTX* ctx)
+{
+ return ctx->GetStats().misses_;
+}
+
+
+long SSL_CTX_sess_timeouts(SSL_CTX* ctx)
+{
+ return ctx->GetStats().timeouts_;
+}
+
+
+long SSL_CTX_sess_number(SSL_CTX* ctx)
+{
+ return ctx->GetStats().number_;
+}
+
+
+long SSL_CTX_sess_get_cache_size(SSL_CTX* ctx)
+{
+ return ctx->GetStats().getCacheSize_;
+}
+// end session stats TODO:
+
+
+int SSL_CTX_get_verify_mode(SSL_CTX* ctx)
+{
+ return ctx->GetStats().verifyMode_;
+}
+
+
+int SSL_get_verify_mode(SSL* ssl)
+{
+ return ssl->getSecurity().GetContext()->GetStats().verifyMode_;
+}
+
+
+int SSL_CTX_get_verify_depth(SSL_CTX* ctx)
+{
+ return ctx->GetStats().verifyDepth_;
+}
+
+
+int SSL_get_verify_depth(SSL* ssl)
+{
+ return ssl->getSecurity().GetContext()->GetStats().verifyDepth_;
+}
+
+
+long SSL_CTX_set_options(SSL_CTX* ctx, long options)
+{
+ ProtocolVersion pv= ctx->getMethod()->getVersion();
+ bool multi_proto= ctx->getMethod()->multipleProtocol();
+ unsigned long ssl_ctx_mask= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
+
+ do
+ {
+ if (options == 0)
+ break;
+ // only TLSv1.1
+ if ((options & ssl_ctx_mask) == ssl_ctx_mask)
+ {
+ pv.minor_= 2;
+ multi_proto= false;
+ break;
+ }
+ // only TLSv1
+ ssl_ctx_mask= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1_1;
+ if((options & ssl_ctx_mask) == ssl_ctx_mask)
+ {
+ pv.minor_= 1;
+ multi_proto= false;
+ break;
+ }
+ // TLSv1.1 and TLSv1
+ ssl_ctx_mask= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
+ if((options & ssl_ctx_mask) == ssl_ctx_mask)
+ {
+ pv.minor_= 2;
+ multi_proto= true;
+ break;
+ }
+ }while(0);
+
+ SSL_METHOD *meth= NEW_YS SSL_METHOD(ctx->getMethod()->getSide(), ProtocolVersion(3,pv.minor_), multi_proto);
+ ctx->SetMethod(meth);
+ return SSL_SUCCESS;
+}
+
+
+void SSL_CTX_set_info_callback(SSL_CTX*, void (*)())
+{
+ // TDOD:
+}
+
+
+void OpenSSL_add_all_algorithms() // compatibility only
+{}
+
+
+int SSL_library_init() // compatiblity only
+{
+ return 1;
+}
+
+
+DH* DH_new(void)
+{
+ DH* dh = NEW_YS DH;
+ if (dh)
+ dh->p = dh->g = 0;
+ return dh;
+}
+
+
+void DH_free(DH* dh)
+{
+ ysDelete(dh->g);
+ ysDelete(dh->p);
+ ysDelete(dh);
+}
+
+
+// convert positive big-endian num of length sz into retVal, which may need to
+// be created
+BIGNUM* BN_bin2bn(const unsigned char* num, int sz, BIGNUM* retVal)
+{
+ bool created = false;
+ mySTL::auto_ptr<BIGNUM> bn;
+
+ if (!retVal) {
+ created = true;
+ bn.reset(NEW_YS BIGNUM);
+ retVal = bn.get();
+ }
+
+ retVal->assign(num, sz);
+
+ if (created)
+ return bn.release();
+ else
+ return retVal;
+}
+
+
+unsigned long ERR_get_error_line_data(const char**, int*, const char**, int *)
+{
+ //return SSL_NOT_IMPLEMENTED;
+ return 0;
+}
+
+
+void ERR_print_errors_fp(FILE* /*fp*/)
+{
+ // need ssl access to implement TODO:
+ //fprintf(fp, "%s", ssl.get_states().errorString_.c_str());
+}
+
+
+char* ERR_error_string(unsigned long errNumber, char* buffer)
+{
+ static char* msg = (char*)"Please supply a buffer for error string";
+
+ if (buffer) {
+ SetErrorString(YasslError(errNumber), buffer);
+ return buffer;
+ }
+
+ return msg;
+}
+
+
+const char* X509_verify_cert_error_string(long /* error */)
+{
+ // TODO:
+ static const char* msg = "Not Implemented";
+ return msg;
+}
+
+
+const EVP_MD* EVP_md5(void)
+{
+ static const char* type = "MD5";
+ return type;
+}
+
+
+const EVP_CIPHER* EVP_des_ede3_cbc(void)
+{
+ static const char* type = "DES-EDE3-CBC";
+ return type;
+}
+
+
+int EVP_BytesToKey(const EVP_CIPHER* type, const EVP_MD* md, const byte* salt,
+ const byte* data, int sz, int count, byte* key, byte* iv)
+{
+ // only support MD5 for now
+ if (strncmp(md, "MD5", 3)) return 0;
+
+ int keyLen = 0;
+ int ivLen = 0;
+
+ // only support CBC DES and AES for now
+ if (strncmp(type, "DES-CBC", 7) == 0) {
+ keyLen = DES_KEY_SZ;
+ ivLen = DES_IV_SZ;
+ }
+ else if (strncmp(type, "DES-EDE3-CBC", 12) == 0) {
+ keyLen = DES_EDE_KEY_SZ;
+ ivLen = DES_IV_SZ;
+ }
+ else if (strncmp(type, "AES-128-CBC", 11) == 0) {
+ keyLen = AES_128_KEY_SZ;
+ ivLen = AES_IV_SZ;
+ }
+ else if (strncmp(type, "AES-192-CBC", 11) == 0) {
+ keyLen = AES_192_KEY_SZ;
+ ivLen = AES_IV_SZ;
+ }
+ else if (strncmp(type, "AES-256-CBC", 11) == 0) {
+ keyLen = AES_256_KEY_SZ;
+ ivLen = AES_IV_SZ;
+ }
+ else
+ return 0;
+
+ yaSSL::MD5 myMD;
+ uint digestSz = myMD.get_digestSize();
+ byte digest[SHA_LEN]; // max size
+
+ int keyLeft = keyLen;
+ int ivLeft = ivLen;
+ int keyOutput = 0;
+
+ while (keyOutput < (keyLen + ivLen)) {
+ int digestLeft = digestSz;
+ // D_(i - 1)
+ if (keyOutput) // first time D_0 is empty
+ myMD.update(digest, digestSz);
+ // data
+ myMD.update(data, sz);
+ // salt
+ if (salt)
+ myMD.update(salt, EVP_SALT_SZ);
+ myMD.get_digest(digest);
+ // count
+ for (int j = 1; j < count; j++) {
+ myMD.update(digest, digestSz);
+ myMD.get_digest(digest);
+ }
+
+ if (keyLeft) {
+ int store = min(keyLeft, static_cast<int>(digestSz));
+ memcpy(&key[keyLen - keyLeft], digest, store);
+
+ keyOutput += store;
+ keyLeft -= store;
+ digestLeft -= store;
+ }
+
+ if (ivLeft && digestLeft) {
+ int store = min(ivLeft, digestLeft);
+ memcpy(&iv[ivLen - ivLeft], &digest[digestSz - digestLeft], store);
+
+ keyOutput += store;
+ ivLeft -= store;
+ }
+ }
+ return keyOutput;
+}
+
+
+
+void DES_set_key_unchecked(const_DES_cblock* key, DES_key_schedule* schedule)
+{
+ memcpy(schedule, key, sizeof(const_DES_cblock));
+}
+
+
+void DES_ede3_cbc_encrypt(const byte* input, byte* output, long sz,
+ DES_key_schedule* ks1, DES_key_schedule* ks2,
+ DES_key_schedule* ks3, DES_cblock* ivec, int enc)
+{
+ DES_EDE des;
+ byte key[DES_EDE_KEY_SZ];
+
+ memcpy(key, *ks1, DES_BLOCK);
+ memcpy(&key[DES_BLOCK], *ks2, DES_BLOCK);
+ memcpy(&key[DES_BLOCK * 2], *ks3, DES_BLOCK);
+
+ if (enc) {
+ des.set_encryptKey(key, *ivec);
+ des.encrypt(output, input, sz);
+ }
+ else {
+ des.set_decryptKey(key, *ivec);
+ des.decrypt(output, input, sz);
+ }
+}
+
+
+// functions for libcurl
+int RAND_status()
+{
+ return 1; /* TaoCrypt provides enough seed */
+}
+
+
+int DES_set_key(const_DES_cblock* key, DES_key_schedule* schedule)
+{
+ memcpy(schedule, key, sizeof(const_DES_cblock));
+ return 1;
+}
+
+
+void DES_set_odd_parity(DES_cblock* key)
+{
+ // not needed now for TaoCrypt
+}
+
+
+void DES_ecb_encrypt(DES_cblock* input, DES_cblock* output,
+ DES_key_schedule* key, int enc)
+{
+ DES des;
+
+ if (enc) {
+ des.set_encryptKey(*key, 0);
+ des.encrypt(*output, *input, DES_BLOCK);
+ }
+ else {
+ des.set_decryptKey(*key, 0);
+ des.decrypt(*output, *input, DES_BLOCK);
+ }
+}
+
+
+void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX* ctx, void* userdata)
+{
+ ctx->SetUserData(userdata);
+}
+
+
+X509* SSL_get_certificate(SSL* ssl)
+{
+ return ssl->getCrypto().get_certManager().get_selfX509();
+}
+
+
+EVP_PKEY* SSL_get_privatekey(SSL* ssl)
+{
+ // only called, not used
+ return 0;
+}
+
+
+void SSL_SESSION_free(SSL_SESSION* session)
+{
+ // managed by singleton
+}
+
+
+
+EVP_PKEY* X509_get_pubkey(X509* x)
+{
+ // called, not used though
+ return 0;
+}
+
+
+int EVP_PKEY_copy_parameters(EVP_PKEY* to, const EVP_PKEY* from)
+{
+ // called, not used though
+ return 0;
+}
+
+
+void EVP_PKEY_free(EVP_PKEY* pkey)
+{
+ // never allocated from above
+}
+
+
+void ERR_error_string_n(unsigned long e, char *buf, size_t len)
+{
+ if (len) ERR_error_string(e, buf);
+}
+
+
+void ERR_free_strings(void)
+{
+ // handled internally
+}
+
+
+void EVP_cleanup(void)
+{
+ // nothing to do yet
+}
+
+
+ASN1_TIME* X509_get_notBefore(X509* x)
+{
+ if (x) return x->GetBefore();
+ return 0;
+}
+
+
+ASN1_TIME* X509_get_notAfter(X509* x)
+{
+ if (x) return x->GetAfter();
+ return 0;
+}
+
+
+SSL_METHOD* SSLv2_client_method(void) /* will never work, no v 2 */
+{
+ return 0;
+}
+
+
+SSL_SESSION* SSL_get1_session(SSL* ssl) /* what's ref count */
+{
+ return SSL_get_session(ssl);
+}
+
+
+void GENERAL_NAMES_free(STACK_OF(GENERAL_NAME) *x)
+{
+ // no extension names supported yet
+}
+
+
+int sk_GENERAL_NAME_num(STACK_OF(GENERAL_NAME) *x)
+{
+ // no extension names supported yet
+ return 0;
+}
+
+
+GENERAL_NAME* sk_GENERAL_NAME_value(STACK_OF(GENERAL_NAME) *x, int i)
+{
+ // no extension names supported yet
+ return 0;
+}
+
+
+unsigned char* ASN1_STRING_data(ASN1_STRING* x)
+{
+ if (x) return x->data;
+ return 0;
+}
+
+
+int ASN1_STRING_length(ASN1_STRING* x)
+{
+ if (x) return x->length;
+ return 0;
+}
+
+
+int ASN1_STRING_type(ASN1_STRING *x)
+{
+ if (x) return x->type;
+ return 0;
+}
+
+
+int X509_NAME_get_index_by_NID(X509_NAME* name,int nid, int lastpos)
+{
+ int idx = -1; // not found
+ int cnPos = -1;
+
+ switch (nid) {
+ case NID_commonName:
+ cnPos = name->GetCnPosition();
+ if (lastpos < cnPos)
+ idx = cnPos;
+ break;
+ }
+
+ return idx;
+}
+
+
+ASN1_STRING* X509_NAME_ENTRY_get_data(X509_NAME_ENTRY* ne)
+{
+ // the same in yaSSL
+ return ne;
+}
+
+
+X509_NAME_ENTRY* X509_NAME_get_entry(X509_NAME* name, int loc)
+{
+ return name->GetEntry(loc);
+}
+
+
+// already formatted, caller responsible for freeing *out
+int ASN1_STRING_to_UTF8(unsigned char** out, ASN1_STRING* in)
+{
+ if (!in) return 0;
+
+ *out = (unsigned char*)malloc(in->length + 1);
+ if (*out) {
+ memcpy(*out, in->data, in->length);
+ (*out)[in->length] = 0;
+ }
+ return in->length;
+}
+
+
+void* X509_get_ext_d2i(X509* x, int nid, int* crit, int* idx)
+{
+ // no extensions supported yet
+ return 0;
+}
+
+
+void MD4_Init(MD4_CTX* md4)
+{
+ // make sure we have a big enough buffer
+ typedef char ok[sizeof(md4->buffer) >= sizeof(TaoCrypt::MD4) ? 1 : -1];
+ (void) sizeof(ok);
+
+ // using TaoCrypt since no dynamic memory allocated
+ // and no destructor will be called
+ new (reinterpret_cast<yassl_pointer>(md4->buffer)) TaoCrypt::MD4();
+}
+
+
+void MD4_Update(MD4_CTX* md4, const void* data, unsigned long sz)
+{
+ reinterpret_cast<TaoCrypt::MD4*>(md4->buffer)->Update(
+ static_cast<const byte*>(data), static_cast<unsigned int>(sz));
+}
+
+
+void MD4_Final(unsigned char* hash, MD4_CTX* md4)
+{
+ reinterpret_cast<TaoCrypt::MD4*>(md4->buffer)->Final(hash);
+}
+
+
+void MD5_Init(MD5_CTX* md5)
+{
+ // make sure we have a big enough buffer
+ typedef char ok[sizeof(md5->buffer) >= sizeof(TaoCrypt::MD5) ? 1 : -1];
+ (void) sizeof(ok);
+
+ // using TaoCrypt since no dynamic memory allocated
+ // and no destructor will be called
+ new (reinterpret_cast<yassl_pointer>(md5->buffer)) TaoCrypt::MD5();
+}
+
+
+void MD5_Update(MD5_CTX* md5, const void* data, unsigned long sz)
+{
+ reinterpret_cast<TaoCrypt::MD5*>(md5->buffer)->Update(
+ static_cast<const byte*>(data), static_cast<unsigned int>(sz));
+}
+
+
+void MD5_Final(unsigned char* hash, MD5_CTX* md5)
+{
+ reinterpret_cast<TaoCrypt::MD5*>(md5->buffer)->Final(hash);
+}
+
+
+int RAND_bytes(unsigned char* buf, int num)
+{
+ RandomPool ran;
+
+ if (ran.GetError()) return 0;
+
+ ran.Fill(buf, num);
+ return 1;
+}
+
+
+int SSL_peek(SSL* ssl, void* buffer, int sz)
+{
+ Data data(min(sz, MAX_RECORD_SIZE), static_cast<opaque*>(buffer));
+ return receiveData(*ssl, data, true);
+}
+
+
+int SSL_pending(SSL* ssl)
+{
+ // Just in case there's pending data that hasn't been processed yet...
+ char c;
+ SSL_peek(ssl, &c, 1);
+
+ return ssl->bufferedData();
+}
+
+
+void SSL_CTX_set_default_passwd_cb(SSL_CTX* ctx, pem_password_cb cb)
+{
+ ctx->SetPasswordCb(cb);
+}
+
+
+int SSLeay_add_ssl_algorithms() // compatibility only
+{
+ return 1;
+}
+
+
+void ERR_remove_state(unsigned long)
+{
+ GetErrors().Remove();
+}
+
+
+int ERR_GET_REASON(int l)
+{
+ return l & 0xfff;
+}
+
+
+unsigned long err_helper(bool peek = false)
+{
+ int ysError = GetErrors().Lookup(peek);
+
+ // translate cert error for libcurl, it uses OpenSSL hex code
+ switch (ysError) {
+ case TaoCrypt::SIG_OTHER_E:
+ return CERTFICATE_ERROR;
+ break;
+ default :
+ return 0;
+ }
+
+ return 0; // shut up compiler
+}
+
+
+unsigned long ERR_peek_error()
+{
+ return err_helper(true);
+}
+
+
+unsigned long ERR_get_error()
+{
+ return err_helper();
+}
+
+
+ // functions for stunnel
+
+ void RAND_screen()
+ {
+ // TODO:
+ }
+
+
+ const char* RAND_file_name(char*, size_t)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ int RAND_write_file(const char*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ int RAND_load_file(const char*, long)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ void RSA_free(RSA*)
+ {
+ // TODO:
+ }
+
+
+ RSA* RSA_generate_key(int, unsigned long, void(*)(int, int, void*), void*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ int X509_LOOKUP_add_dir(X509_LOOKUP*, const char*, long)
+ {
+ // TODO:
+ return SSL_SUCCESS;
+ }
+
+
+ int X509_LOOKUP_load_file(X509_LOOKUP*, const char*, long)
+ {
+ // TODO:
+ return SSL_SUCCESS;
+ }
+
+
+ X509_LOOKUP_METHOD* X509_LOOKUP_hash_dir(void)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ X509_LOOKUP_METHOD* X509_LOOKUP_file(void)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ X509_LOOKUP* X509_STORE_add_lookup(X509_STORE*, X509_LOOKUP_METHOD*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ int X509_STORE_get_by_subject(X509_STORE_CTX*, int, X509_NAME*, X509_OBJECT*)
+ {
+ // TODO:
+ return SSL_SUCCESS;
+ }
+
+
+ X509_STORE* X509_STORE_new(void)
+ {
+ // TODO:
+ return 0;
+ }
+
+ char* SSL_alert_type_string_long(int)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ char* SSL_alert_desc_string_long(int)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ char* SSL_state_string_long(SSL*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ void SSL_CTX_set_tmp_rsa_callback(SSL_CTX*, RSA*(*)(SSL*, int, int))
+ {
+ // TDOD:
+ }
+
+
+ long SSL_CTX_set_timeout(SSL_CTX*, long)
+ {
+ // TDOD:
+ return SSL_SUCCESS;
+ }
+
+
+ int SSL_CTX_use_certificate_chain_file(SSL_CTX*, const char*)
+ {
+ // TDOD:
+ return SSL_SUCCESS;
+ }
+
+
+ int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX*, const char*, int)
+ {
+ // TDOD:
+ return SSL_SUCCESS;
+ }
+
+
+ int SSL_set_rfd(SSL*, int)
+ {
+ return SSL_SUCCESS; // TODO:
+ }
+
+
+ int SSL_set_wfd(SSL*, int)
+ {
+ return SSL_SUCCESS; // TODO:
+ }
+
+
+ int SSL_want_read(SSL*)
+ {
+ return 0; // TODO:
+ }
+
+
+ int SSL_want_write(SSL*)
+ {
+ return 0; // TODO:
+ }
+
+
+ void SSL_set_shutdown(SSL*, int)
+ {
+ // TODO:
+ }
+
+
+ SSL_CIPHER* SSL_get_current_cipher(SSL*)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+ char* SSL_CIPHER_description(SSL_CIPHER*, char*, int)
+ {
+ // TODO:
+ return 0;
+ }
+
+
+
+ // end stunnel needs
+
+ char *yaSSL_ASN1_TIME_to_string(ASN1_TIME *time, char *buf, size_t len)
+ {
+ tm t;
+ static const char *month_names[12]=
+ {
+ "Jan","Feb","Mar","Apr","May","Jun",
+ "Jul","Aug","Sep","Oct","Nov","Dec"
+ };
+
+ TaoCrypt::ASN1_TIME_extract(time->data, time->type, &t);
+#ifdef _WIN32
+ _snprintf(buf, len, "%s %2d %02d:%02d:%02d %d GMT",
+#else
+ snprintf(buf, len, "%s %2d %02d:%02d:%02d %d GMT",
+#endif
+ month_names[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
+ t.tm_sec, t.tm_year + 1900);
+ return buf;
+ }
+
+
+ void yaSSL_transport_set_ptr(SSL *ssl, void *ptr)
+ {
+ ssl->useSocket().set_transport_ptr(ptr);
+ }
+
+
+ void yaSSL_transport_set_recv_function(SSL *ssl, yaSSL_recv_func_t func)
+ {
+ ssl->useSocket().set_transport_recv_function(func);
+ }
+
+
+ void yaSSL_transport_set_send_function(SSL *ssl, yaSSL_send_func_t func)
+ {
+ ssl->useSocket().set_transport_send_function(func);
+ }
+
+} // extern "C"
+} // namespace