1 /*
2    Copyright (c) 2005, 2014, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; see the file COPYING. If not, write to the
15    Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
16    MA  02110-1335  USA.
17 */
18 
19 /*  SSL source implements all openssl compatibility API functions
20  *
21  *  TODO: notes are mostly api additions to allow compilation with mysql
22  *  they don't affect normal modes but should be provided for completeness
23 
24  *  stunnel functions at end of file
25  */
26 
27 
28 
29 /*  see man pages for function descriptions */
30 
31 #include "runtime.hpp"
32 #include "openssl/ssl.h"
33 #include "handshake.hpp"
34 #include "yassl_int.hpp"
35 #include "md5.hpp"              // for TaoCrypt MD5 size assert
36 #include "md4.hpp"              // for TaoCrypt MD4 size assert
37 #include "file.hpp"             // for TaoCrypt Source
38 #include "coding.hpp"           // HexDecoder
39 #include "helpers.hpp"          // for placement new hack
40 #include "rsa.hpp"              // for TaoCrypt RSA key decode
41 #include "dsa.hpp"              // for TaoCrypt DSA key decode
42 #include <stdio.h>
43 #include <time.h>
44 
45 #ifdef _WIN32
46     #include <windows.h>    // FindFirstFile etc..
47 #else
48     #include <sys/types.h>  // file helper
open_openal(out123_handle * ao)49     #include <sys/stat.h>   // stat
50     #include <dirent.h>     // opendir
51 #endif
52 
53 
54 namespace yaSSL {
55 
56 
57 
58 int read_file(SSL_CTX* ctx, const char* file, int format, CertType type)
59 {
60     int ret = SSL_SUCCESS;
61 
62     if (format != SSL_FILETYPE_ASN1 && format != SSL_FILETYPE_PEM)
63         return SSL_BAD_FILETYPE;
64 
65     if (file == NULL || !file[0])
66       return SSL_BAD_FILE;
67 
68     FILE* input = fopen(file, "rb");
69     if (!input)
70         return SSL_BAD_FILE;
71 
72     if (type == CA) {
73         // may have a bunch of CAs
74         x509* ptr;
75         while ( (ptr = PemToDer(input, Cert)) )
76             ctx->AddCA(ptr);
77 
78         if (!feof(input)) {
79             fclose(input);
80             return SSL_BAD_FILE;
81         }
82     }
83     else {
84         x509*& x = (type == Cert) ? ctx->certificate_ : ctx->privateKey_;
85 
86         if (format == SSL_FILETYPE_ASN1) {
87             fseek(input, 0, SEEK_END);
88             long sz = ftell(input);
89             rewind(input);
90             x = NEW_YS x509(sz); // takes ownership
91             size_t bytes = fread(x->use_buffer(), sz, 1, input);
92             if (bytes != 1) {
93                 fclose(input);
94                 return SSL_BAD_FILE;
95             }
96         }
97         else {
98             EncryptedInfo info;
99             x = PemToDer(input, type, &info);
100             if (!x) {
101                 fclose(input);
102                 return SSL_BAD_FILE;
103             }
104             if (info.set) {
105                 // decrypt
106                 char password[80];
107                 pem_password_cb cb = ctx->GetPasswordCb();
108                 if (!cb) {
109                     fclose(input);
110                     return SSL_BAD_FILE;
111                 }
112                 int passwordSz = cb(password, sizeof(password), 0,
113                                     ctx->GetUserData());
114                 byte key[AES_256_KEY_SZ];  // max sizes
115                 byte iv[AES_IV_SZ];
116 
117                 // use file's salt for key derivation, but not real iv
118                 TaoCrypt::Source source(info.iv, info.ivSz);
119                 TaoCrypt::HexDecoder dec(source);
120                 memcpy(info.iv, source.get_buffer(), min((uint)sizeof(info.iv),
121                                                          source.size()));
122                 EVP_BytesToKey(info.name, "MD5", info.iv, (byte*)password,
123                                passwordSz, 1, key, iv);
124 
125                 mySTL::auto_ptr<BulkCipher> cipher;
126                 if (strncmp(info.name, "DES-CBC", 7) == 0)
127                     cipher.reset(NEW_YS DES);
128                 else if (strncmp(info.name, "DES-EDE3-CBC", 13) == 0)
129                     cipher.reset(NEW_YS DES_EDE);
130                 else if (strncmp(info.name, "AES-128-CBC", 13) == 0)
131                     cipher.reset(NEW_YS AES(AES_128_KEY_SZ));
132                 else if (strncmp(info.name, "AES-192-CBC", 13) == 0)
133                     cipher.reset(NEW_YS AES(AES_192_KEY_SZ));
134                 else if (strncmp(info.name, "AES-256-CBC", 13) == 0)
135                     cipher.reset(NEW_YS AES(AES_256_KEY_SZ));
136                 else {
137                     fclose(input);
138                     return SSL_BAD_FILE;
139                 }
140                 cipher->set_decryptKey(key, info.iv);
141                 mySTL::auto_ptr<x509> newx(NEW_YS x509(x->get_length()));
142                 cipher->decrypt(newx->use_buffer(), x->get_buffer(),
143                                 x->get_length());
144                 ysDelete(x);
145                 x = newx.release();
146             }
147         }
148     }
149 
150     if (type == PrivateKey && ctx->privateKey_) {
151         // see if key is valid early
152         TaoCrypt::Source rsaSource(ctx->privateKey_->get_buffer(),
153                                    ctx->privateKey_->get_length());
154         TaoCrypt::RSA_PrivateKey rsaKey;
155         rsaKey.Initialize(rsaSource);
156 
157         if (rsaSource.GetError().What()) {
158             // rsa failed see if DSA works
159 
160             TaoCrypt::Source dsaSource(ctx->privateKey_->get_buffer(),
161                                        ctx->privateKey_->get_length());
162             TaoCrypt::DSA_PrivateKey dsaKey;
163             dsaKey.Initialize(dsaSource);
164 
165             if (dsaSource.GetError().What()) {
166                 // neither worked
167                 ret = SSL_FAILURE;
168             }
169         }
170     }
171 
172     fclose(input);
173     return ret;
174 }
175 
176 
177 extern "C" {
178 
179 
180 SSL_METHOD* SSLv3_method()
181 {
182     return SSLv3_client_method();
183 }
184 
185 
186 SSL_METHOD* SSLv3_server_method()
187 {
188     return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,0));
189 }
190 
191 
192 SSL_METHOD* SSLv3_client_method()
193 {
194     return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,0));
195 }
196 
197 
198 SSL_METHOD* TLSv1_server_method()
199 {
200     return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,1));
201 }
202 
203 
204 SSL_METHOD* TLSv1_client_method()
205 {
206     return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,1));
207 }
208 
209 
210 SSL_METHOD* TLSv1_1_server_method()
211 {
212     return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,2));
213 }
214 
215 
216 SSL_METHOD* TLSv1_1_client_method()
217 {
218     return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,2));
219 }
220 
221 
222 SSL_METHOD* SSLv23_server_method()
223 {
224     // compatibility only, no version 2 support, but does SSL 3 and TLS 1
225     return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,2), true);
226 }
227 
228 
229 SSL_METHOD* SSLv23_client_method()
230 {
231     // compatibility only, no version 2 support, but does SSL 3 and TLS 1
232     // though it sends TLS1 hello not SSLv2 so SSLv3 only servers will decline
233     // TODO: maybe add support to send SSLv2 hello ???
234     return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,2), true);
235 }
236 
237 
238 SSL_CTX* SSL_CTX_new(SSL_METHOD* method)
239 {
240     return NEW_YS SSL_CTX(method);
241 }
242 
243 
244 void SSL_CTX_free(SSL_CTX* ctx)
245 {
246     ysDelete(ctx);
247 }
248 
249 
250 SSL* SSL_new(SSL_CTX* ctx)
251 {
252     return NEW_YS SSL(ctx);
253 }
254 
255 
256 void SSL_free(SSL* ssl)
257 {
258     ysDelete(ssl);
259 }
260 
261 
262 int SSL_set_fd(SSL* ssl, YASSL_SOCKET_T fd)
263 {
264     ssl->useSocket().set_fd(fd);
265     return SSL_SUCCESS;
266 }
267 
268 
269 YASSL_SOCKET_T SSL_get_fd(const SSL* ssl)
270 {
271     return ssl->getSocket().get_fd();
272 }
273 
274 
275 // if you get an error from connect see note at top of README
276 int SSL_connect(SSL* ssl)
277 {
278     if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ))
279         ssl->SetError(no_error);
280 
281     if (ssl->GetError() == YasslError(SSL_ERROR_WANT_WRITE)) {
282 
283         ssl->SetError(no_error);
284         ssl->SendWriteBuffered();
285         if (!ssl->GetError())
286             ssl->useStates().UseConnect() =
287                              ConnectState(ssl->getStates().GetConnect() + 1);
288     }
289 
290     ClientState neededState;
291 
292     switch (ssl->getStates().GetConnect()) {
293 
294     case CONNECT_BEGIN :
295         sendClientHello(*ssl);
296         if (!ssl->GetError())
297             ssl->useStates().UseConnect() = CLIENT_HELLO_SENT;
298         /* fall through */
299 
300     case CLIENT_HELLO_SENT :
301         neededState = ssl->getSecurity().get_resuming() ?
302                       serverFinishedComplete : serverHelloDoneComplete;
303         while (ssl->getStates().getClient() < neededState) {
304             if (ssl->GetError()) break;
305             processReply(*ssl);
306             // if resumption failed, reset needed state
307             if (neededState == serverFinishedComplete)
308                 if (!ssl->getSecurity().get_resuming())
309                     neededState = serverHelloDoneComplete;
310         }
311         if (!ssl->GetError())
312             ssl->useStates().UseConnect() = FIRST_REPLY_DONE;
313         /* fall through */
314 
315     case FIRST_REPLY_DONE :
316         if(ssl->getCrypto().get_certManager().sendVerify())
317             sendCertificate(*ssl);
318 
319         if (!ssl->getSecurity().get_resuming())
320             sendClientKeyExchange(*ssl);
321 
322         if(ssl->getCrypto().get_certManager().sendVerify())
323             sendCertificateVerify(*ssl);
324 
325         sendChangeCipher(*ssl);
326         sendFinished(*ssl, client_end);
327         ssl->flushBuffer();
328 
329         if (!ssl->GetError())
330             ssl->useStates().UseConnect() = FINISHED_DONE;
331         /* fall through */
332 
333     case FINISHED_DONE :
334         if (!ssl->getSecurity().get_resuming())
335             while (ssl->getStates().getClient() < serverFinishedComplete) {
336                 if (ssl->GetError()) break;
337                 processReply(*ssl);
338             }
339         if (!ssl->GetError())
340             ssl->useStates().UseConnect() = SECOND_REPLY_DONE;
341         /* fall through */
342 
343     case SECOND_REPLY_DONE :
344         ssl->verifyState(serverFinishedComplete);
345         ssl->useLog().ShowTCP(ssl->getSocket().get_fd());
346 
347         if (ssl->GetError()) {
348             GetErrors().Add(ssl->GetError());
349             return SSL_FATAL_ERROR;
350         }
351         return SSL_SUCCESS;
352 
353     default :
354         return SSL_FATAL_ERROR; // unkown state
355     }
356 }
357 
358 
359 int SSL_write(SSL* ssl, const void* buffer, int sz)
360 {
361     return sendData(*ssl, buffer, sz);
362 }
363 
364 
365 int SSL_read(SSL* ssl, void* buffer, int sz)
366 {
367     Data data(min(sz, MAX_RECORD_SIZE), static_cast<opaque*>(buffer));
368     return receiveData(*ssl, data);
369 }
370 
371 
372 int SSL_accept(SSL* ssl)
373 {
374     if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ))
375         ssl->SetError(no_error);
376 
377     if (ssl->GetError() == YasslError(SSL_ERROR_WANT_WRITE)) {
378         ssl->SetError(no_error);
379         ssl->SendWriteBuffered();
380         if (!ssl->GetError())
381             ssl->useStates().UseAccept() =
382                              AcceptState(ssl->getStates().GetAccept() + 1);
383     }
384 
385     switch (ssl->getStates().GetAccept()) {
386 
387     case ACCEPT_BEGIN :
388         processReply(*ssl);
389         if (!ssl->GetError())
390             ssl->useStates().UseAccept() = ACCEPT_FIRST_REPLY_DONE;
391         /* fall through */
392 
393     case ACCEPT_FIRST_REPLY_DONE :
394         sendServerHello(*ssl);
395 
396         if (!ssl->getSecurity().get_resuming()) {
397             sendCertificate(*ssl);
398 
399             if (ssl->getSecurity().get_connection().send_server_key_)
400                 sendServerKeyExchange(*ssl);
401 
402             if(ssl->getCrypto().get_certManager().verifyPeer())
403                 sendCertificateRequest(*ssl);
404 
405             sendServerHelloDone(*ssl);
406             ssl->flushBuffer();
407         }
408 
409         if (!ssl->GetError())
410             ssl->useStates().UseAccept() = SERVER_HELLO_DONE;
411         /* fall through */
412 
413     case SERVER_HELLO_DONE :
414         if (!ssl->getSecurity().get_resuming()) {
415             while (ssl->getStates().getServer() < clientFinishedComplete) {
416                 if (ssl->GetError()) break;
417                 processReply(*ssl);
418             }
419         }
420         if (!ssl->GetError())
421             ssl->useStates().UseAccept() = ACCEPT_SECOND_REPLY_DONE;
422         /* fall through */
423 
424     case ACCEPT_SECOND_REPLY_DONE :
425         sendChangeCipher(*ssl);
426         sendFinished(*ssl, server_end);
427         ssl->flushBuffer();
428 
429         if (!ssl->GetError())
430             ssl->useStates().UseAccept() = ACCEPT_FINISHED_DONE;
431         /* fall through */
432 
433     case ACCEPT_FINISHED_DONE :
434         if (ssl->getSecurity().get_resuming()) {
435             while (ssl->getStates().getServer() < clientFinishedComplete) {
436                 if (ssl->GetError()) break;
437                 processReply(*ssl);
438             }
439         }
440         if (!ssl->GetError())
441             ssl->useStates().UseAccept() = ACCEPT_THIRD_REPLY_DONE;
442         /* fall through */
443 
444     case ACCEPT_THIRD_REPLY_DONE :
445         ssl->useLog().ShowTCP(ssl->getSocket().get_fd());
446 
447         if (ssl->GetError()) {
448             GetErrors().Add(ssl->GetError());
449             return SSL_FATAL_ERROR;
450         }
451         return SSL_SUCCESS;
452 
453     default:
454         return SSL_FATAL_ERROR; // unknown state
455     }
456 }
457 
458 
459 int SSL_do_handshake(SSL* ssl)
460 {
461     if (ssl->getSecurity().get_parms().entity_ == client_end)
462         return SSL_connect(ssl);
463     else
464         return SSL_accept(ssl);
465 }
466 
467 
468 int SSL_clear(SSL* ssl)
469 {
470     GetErrors().Remove();
471 
472     return SSL_SUCCESS;
473 }
474 
475 
476 int SSL_shutdown(SSL* ssl)
477 {
478     if (!ssl->GetQuietShutdown()) {
479       Alert alert(warning, close_notify);
480       sendAlert(*ssl, alert);
481     }
482     ssl->useLog().ShowTCP(ssl->getSocket().get_fd(), true);
483 
484     GetErrors().Remove();
485 
486     return SSL_SUCCESS;
487 }
488 
489 
490 void SSL_set_quiet_shutdown(SSL *ssl,int mode)
491 {
492     ssl->SetQuietShutdown(mode != 0);
493 }
494 
495 
496 int SSL_get_quiet_shutdown(SSL *ssl)
497 {
498     return ssl->GetQuietShutdown();
499 }
500 
501 
502 /* on by default but allow user to turn off */
503 long SSL_CTX_set_session_cache_mode(SSL_CTX* ctx, long mode)
504 {
505     if (mode == SSL_SESS_CACHE_OFF)
506         ctx->SetSessionCacheOff();
507 
508     if (mode == SSL_SESS_CACHE_NO_AUTO_CLEAR)
509         ctx->SetSessionCacheFlushOff();
510 
511     return SSL_SUCCESS;
512 }
513 
514 
515 SSL_SESSION* SSL_get_session(SSL* ssl)
516 {
517     if (ssl->getSecurity().GetContext()->GetSessionCacheOff())
518         return 0;
519 
520     return GetSessions().lookup(
521         ssl->getSecurity().get_connection().sessionID_);
522 }
523 
524 
525 int SSL_set_session(SSL* ssl, SSL_SESSION* session)
526 {
527     if (ssl->getSecurity().GetContext()->GetSessionCacheOff())
528         return SSL_FAILURE;
529 
530     ssl->set_session(session);
531     return SSL_SUCCESS;
532 }
533 
534 
535 int SSL_session_reused(SSL* ssl)
536 {
537     return ssl->getSecurity().get_resuming();
538 }
539 
540 
541 long SSL_SESSION_set_timeout(SSL_SESSION* sess, long t)
542 {
543     if (!sess)
544         return SSL_ERROR_NONE;
545 
546     sess->SetTimeOut(t);
547     return SSL_SUCCESS;
548 }
549 
550 
551 long SSL_get_default_timeout(SSL* /*ssl*/)
552 {
553     return DEFAULT_TIMEOUT;
554 }
555 
556 
557 void SSL_flush_sessions(SSL_CTX *ctx, long /* tm */)
558 {
559     if (ctx->GetSessionCacheOff())
560         return;
561 
562     GetSessions().Flush();
563 }
564 
565 
566 const char* SSL_get_cipher_name(SSL* ssl)
567 {
568     return SSL_get_cipher(ssl);
569 }
570 
571 
572 const char* SSL_get_cipher(SSL* ssl)
573 {
574     return ssl->getSecurity().get_parms().cipher_name_;
575 }
576 
577 
578 // SSLv2 only, not implemented
579 char* SSL_get_shared_ciphers(SSL* /*ssl*/, char* buf, int len)
580 {
581     return strncpy(buf, "Not Implemented, SSLv2 only", len);
582 }
583 
584 
585 const char* SSL_get_cipher_list(SSL* ssl, int priority)
586 {
587     if (priority < 0 || priority >= MAX_CIPHERS)
588         return 0;
589 
590     if (ssl->getSecurity().get_parms().cipher_list_[priority][0])
591         return ssl->getSecurity().get_parms().cipher_list_[priority];
592 
593     return 0;
594 }
595 
596 
597 int SSL_CTX_set_cipher_list(SSL_CTX* ctx, const char* list)
598 {
599     if (ctx->SetCipherList(list))
600         return SSL_SUCCESS;
601     else
602         return SSL_FAILURE;
603 }
604 
605 
606 const char* SSL_get_version(SSL* ssl)
607 {
608     static const char* version3 =  "SSLv3";
609     static const char* version31 = "TLSv1";
610 
611     return ssl->isTLS() ? version31 : version3;
612 }
613 
614 const char* SSLeay_version(int)
615 {
616     static const char* version = "SSLeay yaSSL compatibility";
617     return version;
618 }
619 
620 
621 int SSL_get_error(SSL* ssl, int /*previous*/)
622 {
623     return ssl->getStates().What();
624 }
625 
626 
627 
628 /* turn on yaSSL zlib compression
629    returns 0 for success, else error (not built in)
630    only need to turn on for client, becuase server on by default if built in
631    but calling for server will tell you whether it's available or not
632 */
633 int SSL_set_compression(SSL* ssl)   /* Chad didn't rename to ya~ because it is prob. bug. */
634 {
635     return ssl->SetCompression();
636 }
637 
638 
639 
640 X509* SSL_get_peer_certificate(SSL* ssl)
641 {
642     return ssl->getCrypto().get_certManager().get_peerX509();
643 }
644 
645 
646 void X509_free(X509* /*x*/)
647 {
648     // peer cert set for deletion during destruction
649     // no need to delete now
650 }
651 
652 
653 X509* X509_STORE_CTX_get_current_cert(X509_STORE_CTX* ctx)
654 {
655     return ctx->current_cert;
656 }
657 
658 
659 int X509_STORE_CTX_get_error(X509_STORE_CTX* ctx)
660 {
661     return ctx->error;
662 }
663 
664 
665 int X509_STORE_CTX_get_error_depth(X509_STORE_CTX* ctx)
666 {
667     return ctx->error_depth;
668 }
669 
670 
671 // copy name into buffer, at most sz bytes, if buffer is null
672 // will malloc buffer, caller responsible for freeing
673 char* X509_NAME_oneline(X509_NAME* name, char* buffer, int sz)
674 {
675     if (!name->GetName()) return buffer;
676 
677     int len    = (int)strlen(name->GetName()) + 1;
678     int copySz = min(len, sz);
679 
680     if (!buffer) {
681         buffer = (char*)malloc(len);
682         if (!buffer) return buffer;
683         copySz = len;
684     }
685 
686     if (copySz == 0)
687         return buffer;
688 
689     memcpy(buffer, name->GetName(), copySz - 1);
690     buffer[copySz - 1] = 0;
691 
692     return buffer;
693 }
694 
695 
696 X509_NAME* X509_get_issuer_name(X509* x)
697 {
698     return  x->GetIssuer();
699 }
700 
701 
702 X509_NAME* X509_get_subject_name(X509* x)
703 {
704     return x->GetSubject();
705 }
706 
707 
708 void SSL_load_error_strings()   // compatibility only
709 {}
710 
711 
712 void SSL_set_connect_state(SSL*)
713 {
714     // already a client by default
715 }
716 
717 
718 void SSL_set_accept_state(SSL* ssl)
719 {
720     ssl->useSecurity().use_parms().entity_ = server_end;
721 }
722 
723 
724 long SSL_get_verify_result(SSL*)
725 {
726     // won't get here if not OK
727     return X509_V_OK;
728 }
729 
730 
731 long SSL_CTX_sess_set_cache_size(SSL_CTX* /*ctx*/, long /*sz*/)
732 {
733     // unlimited size, can't set for now
734     return 0;
735 }
736 
737 
738 long SSL_CTX_get_session_cache_mode(SSL_CTX*)
739 {
740     // always 0, unlimited size for now
741     return 0;
742 }
743 
744 
745 long SSL_CTX_set_tmp_dh(SSL_CTX* ctx, DH* dh)
746 {
747     if (ctx->SetDH(*dh))
748         return SSL_SUCCESS;
749     else
750         return SSL_FAILURE;
751 }
752 
753 
754 int SSL_CTX_use_certificate_file(SSL_CTX* ctx, const char* file, int format)
755 {
756     return read_file(ctx, file, format, Cert);
757 }
758 
759 
760 int SSL_CTX_use_PrivateKey_file(SSL_CTX* ctx, const char* file, int format)
761 {
762     return read_file(ctx, file, format, PrivateKey);
763 }
764 
765 
766 void SSL_CTX_set_verify(SSL_CTX* ctx, int mode, VerifyCallback vc)
767 {
768     if (mode & SSL_VERIFY_PEER)
769         ctx->setVerifyPeer();
770 
771     if (mode == SSL_VERIFY_NONE)
772         ctx->setVerifyNone();
773 
774     if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)
775         ctx->setFailNoCert();
776 
777     ctx->setVerifyCallback(vc);
778 }
779 
780 
781 int SSL_CTX_load_verify_locations(SSL_CTX* ctx, const char* file,
782                                   const char* path)
783 {
784     int       ret = SSL_SUCCESS;
785 
786     if (file) ret = read_file(ctx, file, SSL_FILETYPE_PEM, CA);
787 
788     if (ret == SSL_SUCCESS && path) {
789         // call read_file for each reqular file in path
790 #ifdef _WIN32
791 
792         WIN32_FIND_DATA FindFileData;
793         HANDLE hFind;
794 
795         const int DELIMITER_SZ      = 2;
796         const int DELIMITER_STAR_SZ = 3;
797         int pathSz = (int)strlen(path);
798         int nameSz = pathSz + DELIMITER_STAR_SZ + 1; // plus 1 for terminator
799         char* name = NEW_YS char[nameSz];  // directory specification
800         memset(name, 0, nameSz);
801         strncpy(name, path, nameSz - DELIMITER_STAR_SZ - 1);
802         strncat(name, "\\*", DELIMITER_STAR_SZ);
803 
804         hFind = FindFirstFile(name, &FindFileData);
805         if (hFind == INVALID_HANDLE_VALUE) {
806             ysArrayDelete(name);
807             return SSL_BAD_PATH;
808         }
809 
810         do {
811             if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
812                 int curSz = (int)strlen(FindFileData.cFileName);
813                 if (pathSz + curSz + DELIMITER_SZ + 1 > nameSz) {
814                     ysArrayDelete(name);
815                     // plus 1 for terminator
816                     nameSz = pathSz + curSz + DELIMITER_SZ + 1;
817                     name = NEW_YS char[nameSz];
818                 }
819                 memset(name, 0, nameSz);
820                 strncpy(name, path, nameSz - curSz - DELIMITER_SZ - 1);
821                 strncat(name, "\\", DELIMITER_SZ);
822                 strncat(name, FindFileData.cFileName,
823                                             nameSz - pathSz - DELIMITER_SZ - 1);
824                 ret = read_file(ctx, name, SSL_FILETYPE_PEM, CA);
825             }
826         } while (ret == SSL_SUCCESS && FindNextFile(hFind, &FindFileData));
827 
828         ysArrayDelete(name);
829         FindClose(hFind);
830 
831 #else   // _WIN32
832         DIR* dir = opendir(path);
833         if (!dir) return SSL_BAD_PATH;
834 
835         struct dirent* entry;
836         struct stat    buf;
837         const int DELIMITER_SZ = 1;
838         int pathSz = (int)strlen(path);
839         int nameSz = pathSz + DELIMITER_SZ + 1; //plus 1 for null terminator
840         char* name = NEW_YS char[nameSz];  // directory specification
841 
842         while (ret == SSL_SUCCESS && (entry = readdir(dir))) {
843             int curSz = (int)strlen(entry->d_name);
844             if (pathSz + curSz + DELIMITER_SZ + 1 > nameSz) {
845                 ysArrayDelete(name);
846                 nameSz = pathSz + DELIMITER_SZ + curSz + 1;
847                 name = NEW_YS char[nameSz];
848             }
849             memset(name, 0, nameSz);
850             strncpy(name, path, nameSz - curSz - 1);
851             strncat(name, "/",  DELIMITER_SZ);
852             strncat(name, entry->d_name, nameSz - pathSz - DELIMITER_SZ - 1);
853 
854             if (stat(name, &buf) < 0) {
855                 ysArrayDelete(name);
856                 closedir(dir);
857                 return SSL_BAD_STAT;
858             }
859 
860             if (S_ISREG(buf.st_mode))
861                 ret = read_file(ctx, name, SSL_FILETYPE_PEM, CA);
862         }
863 
864         ysArrayDelete(name);
865         closedir(dir);
866 
867 #endif
868     }
869 
870     return ret;
871 }
872 
873 
874 int SSL_CTX_set_default_verify_paths(SSL_CTX* /*ctx*/)
875 {
876     // TODO: figure out way to set/store default path, then call load_verify
877     return SSL_NOT_IMPLEMENTED;
878 }
879 
880 
881 int SSL_CTX_set_session_id_context(SSL_CTX*, const unsigned char*,
882                                     unsigned int)
883 {
884     // No application specific context needed for yaSSL
885     return SSL_SUCCESS;
886 }
887 
888 
889 int SSL_CTX_check_private_key(SSL_CTX* /*ctx*/)
890 {
891     // TODO: check private against public for RSA match
892     return SSL_NOT_IMPLEMENTED;
893 }
894 
895 
896 // TODO: all session stats
897 long SSL_CTX_sess_accept(SSL_CTX* ctx)
898 {
899     return ctx->GetStats().accept_;
900 }
901 
902 
903 long SSL_CTX_sess_connect(SSL_CTX* ctx)
904 {
905     return ctx->GetStats().connect_;
906 }
907 
908 
909 long SSL_CTX_sess_accept_good(SSL_CTX* ctx)
910 {
911     return ctx->GetStats().acceptGood_;
912 }
913 
914 
915 long SSL_CTX_sess_connect_good(SSL_CTX* ctx)
916 {
917     return ctx->GetStats().connectGood_;
918 }
919 
920 
921 long SSL_CTX_sess_accept_renegotiate(SSL_CTX* ctx)
922 {
923     return ctx->GetStats().acceptRenegotiate_;
924 }
925 
926 
927 long SSL_CTX_sess_connect_renegotiate(SSL_CTX* ctx)
928 {
929     return ctx->GetStats().connectRenegotiate_;
930 }
931 
932 
933 long SSL_CTX_sess_hits(SSL_CTX* ctx)
934 {
935     return ctx->GetStats().hits_;
936 }
937 
938 
939 long SSL_CTX_sess_cb_hits(SSL_CTX* ctx)
940 {
941     return ctx->GetStats().cbHits_;
942 }
943 
944 
945 long SSL_CTX_sess_cache_full(SSL_CTX* ctx)
946 {
947     return ctx->GetStats().cacheFull_;
948 }
949 
950 
951 long SSL_CTX_sess_misses(SSL_CTX* ctx)
952 {
953     return ctx->GetStats().misses_;
954 }
955 
956 
957 long SSL_CTX_sess_timeouts(SSL_CTX* ctx)
958 {
959     return ctx->GetStats().timeouts_;
960 }
961 
962 
963 long SSL_CTX_sess_number(SSL_CTX* ctx)
964 {
965     return ctx->GetStats().number_;
966 }
967 
968 
969 long SSL_CTX_sess_get_cache_size(SSL_CTX* ctx)
970 {
971     return ctx->GetStats().getCacheSize_;
972 }
973 // end session stats TODO:
974 
975 
976 int SSL_CTX_get_verify_mode(SSL_CTX* ctx)
977 {
978     return ctx->GetStats().verifyMode_;
979 }
980 
981 
982 int SSL_get_verify_mode(SSL* ssl)
983 {
984     return ssl->getSecurity().GetContext()->GetStats().verifyMode_;
985 }
986 
987 
988 int SSL_CTX_get_verify_depth(SSL_CTX* ctx)
989 {
990     return ctx->GetStats().verifyDepth_;
991 }
992 
993 
994 int SSL_get_verify_depth(SSL* ssl)
995 {
996     return ssl->getSecurity().GetContext()->GetStats().verifyDepth_;
997 }
998 
999 
1000 long SSL_CTX_set_options(SSL_CTX*, long)
1001 {
1002     // TDOD:
1003     return SSL_SUCCESS;
1004 }
1005 
1006 
1007 void SSL_CTX_set_info_callback(SSL_CTX*, void (*)())
1008 {
1009     // TDOD:
1010 }
1011 
1012 
1013 void OpenSSL_add_all_algorithms()  // compatibility only
1014 {}
1015 
1016 
1017 int SSL_library_init()  // compatibility only
1018 {
1019     return 1;
1020 }
1021 
1022 
1023 DH* DH_new(void)
1024 {
1025     DH* dh = NEW_YS DH;
1026     if (dh)
1027         dh->p = dh->g = 0;
1028     return dh;
1029 }
1030 
1031 
1032 void DH_free(DH* dh)
1033 {
1034     ysDelete(dh->g);
1035     ysDelete(dh->p);
1036     ysDelete(dh);
1037 }
1038 
1039 
1040 // convert positive big-endian num of length sz into retVal, which may need to
1041 // be created
1042 BIGNUM* BN_bin2bn(const unsigned char* num, int sz, BIGNUM* retVal)
1043 {
1044     bool created = false;
1045     mySTL::auto_ptr<BIGNUM> bn;
1046 
1047     if (!retVal) {
1048         created = true;
1049         bn.reset(NEW_YS BIGNUM);
1050         retVal = bn.get();
1051     }
1052 
1053     retVal->assign(num, sz);
1054 
1055     if (created)
1056         return bn.release();
1057     else
1058         return retVal;
1059 }
1060 
1061 
1062 unsigned long ERR_get_error_line_data(const char**, int*, const char**, int *)
1063 {
1064     //return SSL_NOT_IMPLEMENTED;
1065     return 0;
1066 }
1067 
1068 
1069 void ERR_print_errors_fp(FILE* /*fp*/)
1070 {
1071     // need ssl access to implement TODO:
1072     //fprintf(fp, "%s", ssl.get_states().errorString_.c_str());
1073 }
1074 
1075 
1076 char* ERR_error_string(unsigned long errNumber, char* buffer)
1077 {
1078   static char* msg = (char*)"Please supply a buffer for error string";
1079 
1080     if (buffer) {
1081         SetErrorString(YasslError(errNumber), buffer);
1082         return buffer;
1083     }
1084 
1085     return msg;
1086 }
1087 
1088 
1089 const char* X509_verify_cert_error_string(long /* error */)
1090 {
1091     // TODO:
1092     static const char* msg = "Not Implemented";
1093     return msg;
1094 }
1095 
1096 
1097 const EVP_MD* EVP_md5(void)
1098 {
1099     static const char* type = "MD5";
1100     return type;
1101 }
1102 
1103 
1104 const EVP_CIPHER* EVP_des_ede3_cbc(void)
1105 {
1106     static const char* type = "DES-EDE3-CBC";
1107     return type;
1108 }
1109 
1110 
1111 int EVP_BytesToKey(const EVP_CIPHER* type, const EVP_MD* md, const byte* salt,
1112                    const byte* data, int sz, int count, byte* key, byte* iv)
1113 {
1114     // only support MD5 for now
1115     if (strncmp(md, "MD5", 3)) return 0;
1116 
1117     int keyLen = 0;
1118     int ivLen  = 0;
1119 
1120     // only support CBC DES and AES for now
1121     if (strncmp(type, "DES-CBC", 7) == 0) {
1122         keyLen = DES_KEY_SZ;
1123         ivLen  = DES_IV_SZ;
1124     }
1125     else if (strncmp(type, "DES-EDE3-CBC", 12) == 0) {
1126         keyLen = DES_EDE_KEY_SZ;
1127         ivLen  = DES_IV_SZ;
1128     }
1129     else if (strncmp(type, "AES-128-CBC", 11) == 0) {
1130         keyLen = AES_128_KEY_SZ;
1131         ivLen  = AES_IV_SZ;
1132     }
1133     else if (strncmp(type, "AES-192-CBC", 11) == 0) {
1134         keyLen = AES_192_KEY_SZ;
1135         ivLen  = AES_IV_SZ;
1136     }
1137     else if (strncmp(type, "AES-256-CBC", 11) == 0) {
1138         keyLen = AES_256_KEY_SZ;
1139         ivLen  = AES_IV_SZ;
1140     }
1141     else
1142         return 0;
1143 
1144     yaSSL::MD5 myMD;
1145     uint digestSz = myMD.get_digestSize();
1146     byte digest[SHA_LEN];                   // max size
1147 
1148     int keyLeft   = keyLen;
1149     int ivLeft    = ivLen;
1150     int keyOutput = 0;
1151 
1152     while (keyOutput < (keyLen + ivLen)) {
1153         int digestLeft = digestSz;
1154         // D_(i - 1)
1155         if (keyOutput)                      // first time D_0 is empty
1156             myMD.update(digest, digestSz);
1157         // data
1158         myMD.update(data, sz);
1159         // salt
1160         if (salt)
1161             myMD.update(salt, EVP_SALT_SZ);
1162         myMD.get_digest(digest);
1163         // count
1164         for (int j = 1; j < count; j++) {
1165             myMD.update(digest, digestSz);
1166             myMD.get_digest(digest);
1167         }
1168 
1169         if (keyLeft) {
1170             int store = min(keyLeft, static_cast<int>(digestSz));
1171             memcpy(&key[keyLen - keyLeft], digest, store);
1172 
1173             keyOutput  += store;
1174             keyLeft    -= store;
1175             digestLeft -= store;
1176         }
1177 
1178         if (ivLeft && digestLeft) {
1179             int store = min(ivLeft, digestLeft);
1180             memcpy(&iv[ivLen - ivLeft], &digest[digestSz - digestLeft], store);
1181 
1182             keyOutput += store;
1183             ivLeft    -= store;
1184         }
1185     }
1186     return keyOutput;
1187 }
1188 
1189 
1190 
1191 void DES_set_key_unchecked(const_DES_cblock* key, DES_key_schedule* schedule)
1192 {
1193     memcpy(schedule, key, sizeof(const_DES_cblock));
1194 }
1195 
1196 
1197 void DES_ede3_cbc_encrypt(const byte* input, byte* output, long sz,
1198                           DES_key_schedule* ks1, DES_key_schedule* ks2,
1199                           DES_key_schedule* ks3, DES_cblock* ivec, int enc)
1200 {
1201     DES_EDE des;
1202     byte key[DES_EDE_KEY_SZ];
1203 
1204     memcpy(key, *ks1, DES_BLOCK);
1205     memcpy(&key[DES_BLOCK], *ks2, DES_BLOCK);
1206     memcpy(&key[DES_BLOCK * 2], *ks3, DES_BLOCK);
1207 
1208     if (enc) {
1209         des.set_encryptKey(key, *ivec);
1210         des.encrypt(output, input, sz);
1211     }
1212     else {
1213         des.set_decryptKey(key, *ivec);
1214         des.decrypt(output, input, sz);
1215     }
1216 }
1217 
1218 
1219 // functions for libcurl
1220 int RAND_status()
1221 {
1222     return 1;  /* TaoCrypt provides enough seed */
1223 }
1224 
1225 
1226 int DES_set_key(const_DES_cblock* key, DES_key_schedule* schedule)
1227 {
1228     memcpy(schedule, key, sizeof(const_DES_cblock));
1229     return 1;
1230 }
1231 
1232 
1233 void DES_set_odd_parity(DES_cblock* key)
1234 {
1235     // not needed now for TaoCrypt
1236 }
1237 
1238 
1239 void DES_ecb_encrypt(DES_cblock* input, DES_cblock* output,
1240                      DES_key_schedule* key, int enc)
1241 {
1242     DES  des;
1243 
1244     if (enc) {
1245         des.set_encryptKey(*key, 0);
1246         des.encrypt(*output, *input, DES_BLOCK);
1247     }
1248     else {
1249         des.set_decryptKey(*key, 0);
1250         des.decrypt(*output, *input, DES_BLOCK);
1251     }
1252 }
1253 
1254 
1255 void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX* ctx, void* userdata)
1256 {
1257     ctx->SetUserData(userdata);
1258 }
1259 
1260 
1261 X509* SSL_get_certificate(SSL* ssl)
1262 {
1263     return ssl->getCrypto().get_certManager().get_selfX509();
1264 }
1265 
1266 
1267 EVP_PKEY* SSL_get_privatekey(SSL* ssl)
1268 {
1269     // only called, not used
1270     return 0;
1271 }
1272 
1273 
1274 void SSL_SESSION_free(SSL_SESSION* session)
1275 {
1276     // managed by singleton
1277 }
1278 
1279 
1280 
1281 EVP_PKEY* X509_get_pubkey(X509* x)
1282 {
1283     // called, not used though
1284     return 0;
1285 }
1286 
1287 
1288 int EVP_PKEY_copy_parameters(EVP_PKEY* to, const EVP_PKEY* from)
1289 {
1290     // called, not used though
1291     return 0;
1292 }
1293 
1294 
1295 void EVP_PKEY_free(EVP_PKEY* pkey)
1296 {
1297     // never allocated from above
1298 }
1299 
1300 
1301 void ERR_error_string_n(unsigned long e, char *buf, size_t len)
1302 {
1303     if (len) ERR_error_string(e, buf);
1304 }
1305 
1306 
1307 void ERR_free_strings(void)
1308 {
1309     // handled internally
1310 }
1311 
1312 
1313 void EVP_cleanup(void)
1314 {
1315     // nothing to do yet
1316 }
1317 
1318 
1319 ASN1_TIME* X509_get_notBefore(X509* x)
1320 {
1321     if (x) return x->GetBefore();
1322     return 0;
1323 }
1324 
1325 
1326 ASN1_TIME* X509_get_notAfter(X509* x)
1327 {
1328     if (x) return x->GetAfter();
1329     return 0;
1330 }
1331 
1332 
1333 SSL_METHOD* SSLv2_client_method(void)   /* will never work, no v 2    */
1334 {
1335     return 0;
1336 }
1337 
1338 
1339 SSL_SESSION* SSL_get1_session(SSL* ssl)  /* what's ref count */
1340 {
1341     return SSL_get_session(ssl);
1342 }
1343 
1344 
1345 void GENERAL_NAMES_free(STACK_OF(GENERAL_NAME) *x)
1346 {
1347     // no extension names supported yet
1348 }
1349 
1350 
1351 int sk_GENERAL_NAME_num(STACK_OF(GENERAL_NAME) *x)
1352 {
1353     // no extension names supported yet
1354     return 0;
1355 }
1356 
1357 
1358 GENERAL_NAME* sk_GENERAL_NAME_value(STACK_OF(GENERAL_NAME) *x, int i)
1359 {
1360     // no extension names supported yet
1361     return 0;
1362 }
1363 
1364 
1365 unsigned char* ASN1_STRING_data(ASN1_STRING* x)
1366 {
1367     if (x) return x->data;
1368     return 0;
1369 }
1370 
1371 
1372 int ASN1_STRING_length(ASN1_STRING* x)
1373 {
1374     if (x) return x->length;
1375     return 0;
1376 }
1377 
1378 
1379 int ASN1_STRING_type(ASN1_STRING *x)
1380 {
1381     if (x) return x->type;
1382     return 0;
1383 }
1384 
1385 
1386 int X509_NAME_get_index_by_NID(X509_NAME* name,int nid, int lastpos)
1387 {
1388     int idx = -1;  // not found
1389     int cnPos = -1;
1390 
1391     switch (nid) {
1392     case NID_commonName:
1393         cnPos = name->GetCnPosition();
1394         if (lastpos < cnPos)
1395             idx = cnPos;
1396         break;
1397     }
1398 
1399     return idx;
1400 }
1401 
1402 
1403 ASN1_STRING* X509_NAME_ENTRY_get_data(X509_NAME_ENTRY* ne)
1404 {
1405     // the same in yaSSL
1406     return ne;
1407 }
1408 
1409 
1410 X509_NAME_ENTRY* X509_NAME_get_entry(X509_NAME* name, int loc)
1411 {
1412     return name->GetEntry(loc);
1413 }
1414 
1415 
1416 // already formatted, caller responsible for freeing *out
1417 int ASN1_STRING_to_UTF8(unsigned char** out, ASN1_STRING* in)
1418 {
1419     if (!in) return 0;
1420 
1421     *out = (unsigned char*)malloc(in->length + 1);
1422     if (*out) {
1423         memcpy(*out, in->data, in->length);
1424         (*out)[in->length] = 0;
1425     }
1426     return in->length;
1427 }
1428 
1429 
1430 void* X509_get_ext_d2i(X509* x, int nid, int* crit, int* idx)
1431 {
1432     // no extensions supported yet
1433     return 0;
1434 }
1435 
1436 
1437 void MD4_Init(MD4_CTX* md4)
1438 {
1439     // make sure we have a big enough buffer
1440     typedef char ok[sizeof(md4->buffer) >= sizeof(TaoCrypt::MD4) ? 1 : -1];
1441     (void) sizeof(ok);
1442 
1443     // using TaoCrypt since no dynamic memory allocated
1444     // and no destructor will be called
1445     new (reinterpret_cast<yassl_pointer>(md4->buffer)) TaoCrypt::MD4();
1446 }
1447 
1448 
1449 void MD4_Update(MD4_CTX* md4, const void* data, unsigned long sz)
1450 {
1451     reinterpret_cast<TaoCrypt::MD4*>(md4->buffer)->Update(
1452                 static_cast<const byte*>(data), static_cast<unsigned int>(sz));
1453 }
1454 
1455 
1456 void MD4_Final(unsigned char* hash, MD4_CTX* md4)
1457 {
1458     reinterpret_cast<TaoCrypt::MD4*>(md4->buffer)->Final(hash);
1459 }
1460 
1461 
1462 void MD5_Init(MD5_CTX* md5)
1463 {
1464     // make sure we have a big enough buffer
1465     typedef char ok[sizeof(md5->buffer) >= sizeof(TaoCrypt::MD5) ? 1 : -1];
1466     (void) sizeof(ok);
1467 
1468     // using TaoCrypt since no dynamic memory allocated
1469     // and no destructor will be called
1470     new (reinterpret_cast<yassl_pointer>(md5->buffer)) TaoCrypt::MD5();
1471 }
1472 
1473 
1474 void MD5_Update(MD5_CTX* md5, const void* data, unsigned long sz)
1475 {
1476     reinterpret_cast<TaoCrypt::MD5*>(md5->buffer)->Update(
1477                 static_cast<const byte*>(data), static_cast<unsigned int>(sz));
1478 }
1479 
1480 
1481 void MD5_Final(unsigned char* hash, MD5_CTX* md5)
1482 {
1483     reinterpret_cast<TaoCrypt::MD5*>(md5->buffer)->Final(hash);
1484 }
1485 
1486 
1487 int RAND_bytes(unsigned char* buf, int num)
1488 {
1489     RandomPool ran;
1490 
1491     if (ran.GetError()) return 0;
1492 
1493     ran.Fill(buf, num);
1494     return 1;
1495 }
1496 
1497 
1498 int SSL_peek(SSL* ssl, void* buffer, int sz)
1499 {
1500     Data data(min(sz, MAX_RECORD_SIZE), static_cast<opaque*>(buffer));
1501     return receiveData(*ssl, data, true);
1502 }
1503 
1504 
1505 int SSL_pending(SSL* ssl)
1506 {
1507     return ssl->bufferedData();
1508 }
1509 
1510 
1511 void SSL_CTX_set_default_passwd_cb(SSL_CTX* ctx, pem_password_cb cb)
1512 {
1513     ctx->SetPasswordCb(cb);
1514 }
1515 
1516 
1517 int SSLeay_add_ssl_algorithms()  // compatibility only
1518 {
1519     return 1;
1520 }
1521 
1522 
1523 void ERR_remove_state(unsigned long)
1524 {
1525     if (HasErrors())
1526        GetErrors().Remove();
1527 }
1528 
1529 
1530 int ERR_GET_REASON(int l)
1531 {
1532     return l & 0xfff;
1533 }
1534 
1535 
1536 unsigned long err_helper(bool peek = false)
1537 {
1538     int ysError = GetErrors().Lookup(peek);
1539 
1540     // translate cert error for libcurl, it uses OpenSSL hex code
1541     switch (ysError) {
1542     case TaoCrypt::SIG_OTHER_E:
1543         return CERTFICATE_ERROR;
1544         break;
1545     default :
1546         return 0;
1547     }
1548 
1549     return 0;  // shut up compiler
1550 }
1551 
1552 
1553 unsigned long ERR_peek_error()
1554 {
1555     return err_helper(true);
1556 }
1557 
1558 
1559 unsigned long ERR_get_error()
1560 {
1561     return err_helper();
1562 }
1563 
1564 
1565     // functions for stunnel
1566 
1567     void RAND_screen()
1568     {
1569         // TODO:
1570     }
1571 
1572 
1573     const char* RAND_file_name(char*, size_t)
1574     {
1575         // TODO:
1576         return 0;
1577     }
1578 
1579 
1580     int RAND_write_file(const char*)
1581     {
1582         // TODO:
1583         return 0;
1584     }
1585 
1586 
1587     int RAND_load_file(const char*, long)
1588     {
1589         // TODO:
1590         return 0;
1591     }
1592 
1593 
1594     void RSA_free(RSA*)
1595     {
1596         // TODO:
1597     }
1598 
1599 
1600     RSA* RSA_generate_key(int, unsigned long, void(*)(int, int, void*), void*)
1601     {
1602         //  TODO:
1603         return 0;
1604     }
1605 
1606 
1607     int X509_LOOKUP_add_dir(X509_LOOKUP*, const char*, long)
1608     {
1609         // TODO:
1610         return SSL_SUCCESS;
1611     }
1612 
1613 
1614     int X509_LOOKUP_load_file(X509_LOOKUP*, const char*, long)
1615     {
1616         // TODO:
1617         return SSL_SUCCESS;
1618     }
1619 
1620 
1621     X509_LOOKUP_METHOD* X509_LOOKUP_hash_dir(void)
1622     {
1623         // TODO:
1624         return 0;
1625     }
1626 
1627 
1628     X509_LOOKUP_METHOD* X509_LOOKUP_file(void)
1629     {
1630         // TODO:
1631         return 0;
1632     }
1633 
1634 
1635     X509_LOOKUP* X509_STORE_add_lookup(X509_STORE*, X509_LOOKUP_METHOD*)
1636     {
1637         // TODO:
1638         return 0;
1639     }
1640 
1641 
1642     int X509_STORE_get_by_subject(X509_STORE_CTX*, int, X509_NAME*, X509_OBJECT*)
1643     {
1644         // TODO:
1645         return SSL_SUCCESS;
1646     }
1647 
1648 
1649     X509_STORE* X509_STORE_new(void)
1650     {
1651         // TODO:
1652         return 0;
1653     }
1654 
1655     char* SSL_alert_type_string_long(int)
1656     {
1657         // TODO:
1658         return 0;
1659     }
1660 
1661 
1662     char* SSL_alert_desc_string_long(int)
1663     {
1664         // TODO:
1665         return 0;
1666     }
1667 
1668 
1669     char* SSL_state_string_long(SSL*)
1670     {
1671         // TODO:
1672         return 0;
1673     }
1674 
1675 
1676     void SSL_CTX_set_tmp_rsa_callback(SSL_CTX*, RSA*(*)(SSL*, int, int))
1677     {
1678         // TDOD:
1679     }
1680 
1681 
1682     long SSL_CTX_set_timeout(SSL_CTX*, long)
1683     {
1684         // TDOD:
1685         return SSL_SUCCESS;
1686     }
1687 
1688 
1689     int SSL_CTX_use_certificate_chain_file(SSL_CTX* ctx, const char* file)
1690     {
1691         // For the moment, treat like use_certificate_file
1692         return read_file(ctx, file, SSL_FILETYPE_PEM, Cert);
1693     }
1694 
1695 
1696     int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX*, const char*, int)
1697     {
1698         // TDOD:
1699         return SSL_SUCCESS;
1700     }
1701 
1702 
1703     int SSL_set_rfd(SSL*, int)
1704     {
1705         return SSL_SUCCESS; // TODO:
1706     }
1707 
1708 
1709     int SSL_set_wfd(SSL*, int)
1710     {
1711         return SSL_SUCCESS; // TODO:
1712     }
1713 
1714 
1715     int SSL_want_read(SSL*)
1716     {
1717         return 0; // TODO:
1718     }
1719 
1720 
1721     int SSL_want_write(SSL*)
1722     {
1723         return 0; // TODO:
1724     }
1725 
1726 
1727     void SSL_set_shutdown(SSL*, int)
1728     {
1729         // TODO:
1730     }
1731 
1732     SSL_CIPHER* SSL_get_current_cipher(SSL*)
1733     {
1734         // TODO:
1735         return 0;
1736     }
1737 
1738 
1739     char* SSL_CIPHER_description(SSL_CIPHER*, char*, int)
1740     {
1741         // TODO:
1742         return 0;
1743     }
1744 
1745     // end stunnel needs
1746 
1747     char *yaSSL_ASN1_TIME_to_string(const ASN1_TIME *time, char *buf, size_t len)
1748     {
1749       tm t;
1750       static const char *month_names[12]=
1751       {
1752         "Jan","Feb","Mar","Apr","May","Jun",
1753         "Jul","Aug","Sep","Oct","Nov","Dec"
1754       };
1755 
1756       TaoCrypt::ASN1_TIME_extract(time->data, time->type, &t);
1757       snprintf(buf, len, "%s %2d %02d:%02d:%02d %d GMT",
1758                month_names[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
1759                t.tm_sec, t.tm_year + 1900);
1760       return buf;
1761     }
1762 
1763 
1764     void yaSSL_transport_set_ptr(SSL *ssl, void *ptr)
1765     {
1766       ssl->useSocket().set_transport_ptr(ptr);
1767     }
1768 
1769 
1770     void yaSSL_transport_set_recv_function(SSL *ssl, yaSSL_recv_func_t func)
1771     {
1772       ssl->useSocket().set_transport_recv_function(func);
1773     }
1774 
1775 
1776     void yaSSL_transport_set_send_function(SSL *ssl, yaSSL_send_func_t func)
1777     {
1778       ssl->useSocket().set_transport_send_function(func);
1779     }
1780 
1781 } // extern "C"
1782 } // namespace
1783