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