DCL 4.0
Loading...
Searching...
No Matches
SSLSocket.cpp
Go to the documentation of this file.
1/*
2 * REFERENCES
3 *
4 * OPENSSL
5 * http://www.rtfm.com/sslbook/
6 * http://www.openssl.org/
7 *
8 * SCHANNEL
9 * Windows SDKs
10 * MSDN/Win32 and COM/Security/Authentication/
11 * Using Authentication/Using SSPI/
12 * Creating a Secure Connection Using Schannel
13 *
14 * Windows SDKs 2003
15 * Samples/
16 */
17
18#include <dcl/Config.h>
19
20#if __DCL_WINDOWS
21 #include <winsock2.h>
22#else
23 #include <sys/socket.h>
24#endif
25
26#if __DCL_USE_OPENSSL
27 #include <openssl/ssl.h>
28 #include <openssl/err.h>
29 #include <dcl/Thread.h>
30#elif __DCL_USE_SCHANNEL
31 #define SEC_FAILED(ss) (ss < 0)
32#endif
33
34#include <dcl/Object.h>
35#include <dcl/Charset.h>
36#include <dcl/Numeric.h>
37#include <dcl/SSLSocket.h>
38
39__DCL_BEGIN_NAMESPACE
40
41#if __DCL_DEBUG
42 #undef __THIS_FILE__
43 static const char_t __THIS_FILE__[] = __T("dcl/SSLSocket.cpp");
44#endif
45
47
48SSLException::SSLException(Exception* _cause)
49 : Exception(_cause)
50{
51}
52
53#if __DCL_USE_OPENSSL
54SSLException::SSLException()
56{
57 unsigned long e = ERR_get_error();
58 char buf[256];
59 ERR_error_string_n(e, buf, sizeof(buf));
60
61 LocaleDecoder decoder;
62 __message = decoder.decode(buf);
63}
64
65#elif __DCL_USE_SCHANNEL
66static HMODULE __hSecure32_dll__ = NULL;
67
68static String __GetStatusMessage(SECURITY_STATUS _ss)
69{
70 if (__hSecure32_dll__ == NULL)
71 __hSecure32_dll__ = LoadLibraryW(__T("secure32.dll"));
72
73 StringBuilder sb;
74 wchar_t* msg = NULL;
75 DWORD dwLength = FormatMessageW(
76 FORMAT_MESSAGE_ALLOCATE_BUFFER |
77 FORMAT_MESSAGE_FROM_SYSTEM |
78 FORMAT_MESSAGE_IGNORE_INSERTS,
79 __hSecure32_dll__,
80 _ss,
81 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
82 (LPWSTR) &msg,
83 0,
84 NULL
85 );
86
87 if (dwLength > 0) {
88 for ( ; dwLength; dwLength--)
89 if (!(msg[dwLength - 1] == L'\r' || msg[dwLength - 1] == L'\n'))
90 break;
91
92 sb.assign(msg, dwLength);
93 LocalFree(msg);
94
95 sb += L" (ERROR=";
96 sb += UInteger::toString(_ss, 10);
97 sb += L")";
98 }
99 else
100 sb = L"::FormatMessage Fail!";
101
102 return sb;
103}
104
105SSLException::SSLException(SECURITY_STATUS _ss)
106{
107 __message = __GetStatusMessage(_ss);
108}
109#endif
110
111String SSLException::toString() const
112{
113 return __message;
114}
115
117
118size_t SSLSocket::available() const
120{
121#if __DCL_USE_OPENSSL
122 __DCL_ASSERT_HANDLE(__ctx != NULL);
123 __DCL_ASSERT_HANDLE(__ssl != NULL);
124 __DCL_TRACE2(__T("%d, %d\n"), (int) Socket::available(), SSL_pending(__ssl));
125 return (size_t) SSL_pending(__ssl);
126#else
127 return Socket::available();
128#endif
129}
130
131#if 0
132size_t SSLSocket::read(void* _buf, size_t _n)
134
135size_t SSLSocket::write(const void* _buf, size_t _n)
137
138
139void SSLSocket::bind(const Addr& _my_addr,
140 int _type, int _protocol, bool _reuse
142
143void SSLSocket::accept(SSLSocket& _r)
145
146void SSLSocket::connect(const Addr& _serv_addr)
148#endif
149
150#if __DCL_USE_OPENSSL
151static Thread::OnceType __opensslOnceControl = Thread::ONCE_INIT;
152
153static void __opensslLibraryInit()
154{
155 SSL_library_init();
156 SSL_load_error_strings();
157}
158#endif
159
160#if 0
161int SSLSocket::pem_passwd_cb(char* _buf, int _size, int _rwflag, void* _userdata)
162{
163 SSLSocket* obj = (SSLSocket*) _userdata;
164 return obj->onPermPasswordCallback(_buf, _size, _rwflag);
165}
166
167int SSLSocket::onPermPasswordCallback(char* _buf, int _size, int _rwflag)
168{
169 int n = (int) __defaultPassword.length() > (_size - 1) ? (_size - 1)
170 : (int) __defaultPassword.length();
171 strncpy(_buf, __defaultPassword.data(), n);
172 _buf[n] = '\0';
173 return n;
174}
175
176bool SSLSocket::__opensslContextInit(const char* _keyfile)
177{
178 Thread::once(__opensslOnceControl, __opensslLibraryInit);
179
180 SSL_CTX* ctx = NULL;
181
182 ctx = SSL_CTX_new(SSLv23_method());
183
184
185 if (!(SSL_CTX_use_certificate_chain_file(ctx, "client.pem"))) {
186 __DCL_TRACE0(__T("Can't read certificate file\n"));
187 goto __failed;
188 }
189 SSL_CTX_set_default_passwd_cb(ctx, SSLSocket::pem_passwd_cb);
190 SSL_CTX_set_default_passwd_cb_userdata(ctx, this);
191
192 if (!(SSL_CTX_use_PrivateKey_file(ctx, "client.pem", SSL_FILETYPE_PEM))) {
193 __DCL_TRACE0(__T("Can't read key file\n"));
194 goto __failed;
195 }
196
197#define CA_LIST "root.pem"
198
199 if( !(SSL_CTX_load_verify_locations(ctx, CA_LIST, 0))) {
200 __DCL_TRACE0(__T("Can't read CA list\n"));
201 goto __failed;
202 }
203
204#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
205 SSL_CTX_set_verify_depth(ctx,1);
206#endif
207
208 __ctx = ctx;
209 return true;
210
211__failed:
212 if (ctx)
213 SSL_CTX_free(ctx);
214 return false;
215}
216
217#endif
218
221{
222#if __DCL_USE_OPENSSL
223 Thread::once(__opensslOnceControl, __opensslLibraryInit);
224 __ctx = NULL;
225 __ssl = NULL;
226 SSL_CTX* ctx = SSL_CTX_new(SSLv23_method());
227 if (ctx == NULL)
228 throw new SSLException();
229 __ctx = ctx;
230
231#elif __DCL_USE_SCHANNEL
232 SecInvalidateHandle(&__cred);
233 SecInvalidateHandle(&__ctxt);
234
235 CredHandle cred;
236 SCHANNEL_CRED credData;
237 TimeStamp tsExpiry;
238
239 ZeroMemory(&credData, sizeof(credData));
240 credData.dwVersion = SCHANNEL_CRED_VERSION;
241 // Specify the TLS V1.0 (client-side) security protocol.
242 // credData.grbitEnabledProtocols = SP_PROT_TLS1_CLIENT;
243
244 credData.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
245 credData.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
246
247 SECURITY_STATUS ss = AcquireCredentialsHandleW(
248 NULL, // __in SEC_CHAR* pszPrincipal, default principal
249 UNISP_NAME_W, // __in SEC_CHAR* pszPackage, for Schannel
250 SECPKG_CRED_OUTBOUND, // __in ULONG fCredentialUse,
251 NULL, // __in PLUID pvLogonID, use the current LOGON id
252 &credData, // __in PVOID pAuthData, protocol-specific data
253 NULL, // __in SEC_GET_KEY_FN pGetKeyFn, default
254 NULL, // __in PVOID pvGetKeyArgument, default
255 &cred, // __out PCredHandle phCredential,
256 &tsExpiry // __out PTimeStamp ptsExpiry
257 );
258 if (ss != SEC_E_OK)
259 throw new SSLException(ss);
260
261 __cred = cred;
262#endif
263}
264
270
271SSLSocket::SSLSocket(const String& _addr, uint16_t _port)
273{
274 construct();
275 Socket::open(_addr, _port);
276}
277
279{
280#if __DCL_USE_OPENSSL
281 if (__ssl)
282#elif __DCL_USE_SCHANNEL
283 if (SecIsValidHandle(&__ctxt))
284#endif
285 {
286 try {
287 close();
288 }
289 catch (Exception* cause) {
290 __DCL_TRACE1(__T("Error! SSLSocket::~SSLSocket %ls\n"), cause->toString().data());
291 cause->destroy();
292 }
293 }
294
295#if __DCL_USE_OPENSSL
296 if (__ctx) {
297 SSL_CTX_free(__ctx);
298 #if __DCL_DEBUG
299 __ctx = NULL;
300 #endif
301 }
302
303#elif __DCL_USE_SCHANNEL
304 if (SecIsValidHandle(&__cred)) {
305 SECURITY_STATUS ss = FreeCredentialsHandle(&__cred);
306 #if __DCL_DEBUG
307 if (ss != SEC_E_OK)
308 __DCL_TRACE1(__T("Warning!! [%ls]\n"), __GetStatusMessage(ss).data());
309 SecInvalidateHandle(&__cred);
310 #endif
311 }
312
313#endif
314}
315
318{
319#if __DCL_USE_OPENSSL
320 __DCL_ASSERT_HANDLE(__ssl != NULL);
321 SSL_free(__ssl);
322 __ssl = NULL;
323
324#elif __DCL_USE_SCHANNEL
325 __DCL_ASSERT_HANDLE(SecIsValidHandle(&__ctxt));
326 SECURITY_STATUS ss = DeleteSecurityContext(&__ctxt);
327 #if __DCL_DEBUG
328 if (ss != SEC_E_OK)
329 __DCL_TRACE1(__T("Warning!! [%ls]\n"), __GetStatusMessage(ss).data());
330 #endif
331 SecInvalidateHandle(&__ctxt);
332
333#endif
334
336}
337
338#if 0
339void SSLSocket::bind(const struct sockaddr* _my_addr, socklen_t _addrlen)
341
342void SSLSocket::listen(unsigned _backlog)
344
345void SSLSocket::accept(SSLSocket& r, struct sockaddr* _addr, socklen_t* _addrlen)
347
348#endif
349
350void SSLSocket::connect(const sockaddr* _serv_addr, socklen_t _addrlen)
352{
353 Socket::connect(_serv_addr, _addrlen);
354
355 __DCL_TRACE0(__T("SSLSocket::connect()\n"));
356
357#if __DCL_USE_OPENSSL
358 __DCL_ASSERT_HANDLE(__ctx != NULL);
359 __DCL_ASSERT_HANDLE(__ssl == NULL);
360 __ssl = SSL_new(__ctx);
361 BIO* bio = BIO_new_socket(__handle, BIO_NOCLOSE);
362
363 SSL_set_bio(__ssl, bio, bio);
364
365 if (SSL_connect(__ssl) < 0)
366 throw new IOException(toString(), new SSLException());
367
368#elif __DCL_USE_SCHANNEL
369 DWORD fContextReq = ISC_REQ_SEQUENCE_DETECT |
370 ISC_REQ_REPLAY_DETECT |
371 ISC_REQ_CONFIDENTIALITY |
372 ISC_RET_EXTENDED_ERROR |
373 ISC_REQ_ALLOCATE_MEMORY |
374 ISC_REQ_STREAM;
375
376 SecBufferDesc outBufferDesc;
377 SecBuffer outBuffers[1];
378
379 outBuffers[0].BufferType = SECBUFFER_TOKEN;
380 outBuffers[0].cbBuffer = 0;
381 outBuffers[0].pvBuffer = NULL;
382 outBufferDesc.ulVersion = SECBUFFER_VERSION;
383 outBufferDesc.cBuffers = 1;
384 outBufferDesc.pBuffers = outBuffers;
385
386 CtxtHandle ctxt;
387 ULONG ctxtAttr;
388 TimeStamp tsExpiry;
389
390 SECURITY_STATUS ss = InitializeSecurityContextW(
391 &__cred, // __in PCredHandle phCredential,
392 NULL, // __in_out PCtxtHandle phContext,
393 NULL, // __in SEC_CHAR* pszTargetName,
394 fContextReq, // __in ULONG fContextReq,
395 0, // ULONG Reserved1,
396 0, // __in ULONG TargetDataRep,
397 NULL, // __in_out PSecBufferDesc pInput,
398 0, // ULONG Reserved2,
399 &ctxt, // __in_out PCtxtHandle phNewContext,
400 &outBufferDesc, // __out PSecBufferDesc pOutput,
401 &ctxtAttr, // __out PULONG pfContextAttr,
402 &tsExpiry // __out PTimeStamp ptsExpiry
403 );
404
405 if (FAILED(ss))
406 throw new IOException(toString(), new SSLException(ss));
407
408 __DCL_TRACE1(__T("%ls\n"), __GetStatusMessage(ss).data());
409
410 if (outBuffers[0].cbBuffer != 0 && outBuffers[0].pvBuffer != NULL) {
411 __DCL_TRACE3(__T("%d, %d, [%ls]\n"),
412 outBuffers[0].BufferType,
413 outBuffers[0].cbBuffer,
414 String::tryString((const char*) outBuffers[0].pvBuffer,
415 outBuffers[0].cbBuffer, 8).data()
416 );
417 int n = ::send((UINT_PTR) __handle,
418 (const char*) outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0);
419 if (n == SOCKET_ERROR || n == 0) {
420 FreeContextBuffer(outBuffers[0].pvBuffer);
421 DeleteSecurityContext(&ctxt);
422 throw new IOException(toString(), WSAGetLastError());
423 }
424
425 __DCL_TRACE1(__T("[%d] bytes of Handshake data sent\n"), n);
426 FreeContextBuffer(outBuffers[0].pvBuffer);
427 outBuffers[0].pvBuffer = NULL;
428 }
429
430 // Handshake
431
432 SecBufferDesc inBufferDesc;
433 SecBuffer inBuffers[2];
434
435 DWORD WSAError = 0;
436#define READ_BUFFER_SIZE 0x10000
437 char* readBuffer = (char*) malloc(READ_BUFFER_SIZE);
438 bool fDoRead = true;
439 unsigned int nRead = 0;
440
441 while (ss == SEC_I_CONTINUE_NEEDED ||
442 ss == SEC_E_INCOMPLETE_MESSAGE ||
443 ss == SEC_I_INCOMPLETE_CREDENTIALS) {
444 if (0 == nRead || ss == SEC_E_INCOMPLETE_MESSAGE) {
445 if (fDoRead) {
446 int n = ::recv(
447 (UINT_PTR) __handle,
448 readBuffer + nRead,
449 READ_BUFFER_SIZE - nRead,
450 0
451 );
452 if (n == SOCKET_ERROR) {
453 WSAError = WSAGetLastError();
454 ss = SEC_E_INTERNAL_ERROR;
455 break;
456 }
457 else if (n == 0) {
458 WSAError = WSAECONNRESET;
459 ss = SEC_E_INTERNAL_ERROR;
460 break;
461 }
462 __DCL_TRACE2(__T("Handshake read [%d] [%ls]\n"), n,
463 String::tryString((const char*) readBuffer + nRead, n, 8).data());
464
465 nRead += n;
466 }
467 else
468 fDoRead = true;
469 }
470
471 inBuffers[0].BufferType = SECBUFFER_TOKEN;
472 inBuffers[0].cbBuffer = nRead;
473 inBuffers[0].pvBuffer = readBuffer;
474
475 inBuffers[1].BufferType = SECBUFFER_EMPTY;
476 inBuffers[1].cbBuffer = 0;
477 inBuffers[1].pvBuffer = NULL;
478
479 inBufferDesc.ulVersion = SECBUFFER_VERSION;
480 inBufferDesc.cBuffers = 2;
481 inBufferDesc.pBuffers = inBuffers;
482
483 outBuffers[0].BufferType = SECBUFFER_TOKEN;
484 outBuffers[0].cbBuffer = 0;
485 outBuffers[0].pvBuffer = NULL;
486
487 outBufferDesc.ulVersion = SECBUFFER_VERSION;
488 outBufferDesc.cBuffers = 1;
489 outBufferDesc.pBuffers = outBuffers;
490
491 ss = InitializeSecurityContextW(
492 &__cred,
493 &ctxt,
494 NULL,
495 fContextReq,
496 0,
497 SECURITY_NATIVE_DREP,
498 &inBufferDesc,
499 0,
500 NULL,
501 &outBufferDesc,
502 &ctxtAttr,
503 &tsExpiry
504 );
505
506 if (ss == SEC_E_OK ||
507 ss == SEC_I_CONTINUE_NEEDED ||
508 FAILED(ss) && (ctxtAttr & ISC_RET_EXTENDED_ERROR)) {
509 if (outBuffers[0].cbBuffer != 0 && outBuffers[0].pvBuffer != NULL) {
510 int n = ::send(
511 (UINT_PTR) __handle,
512 (const char*) outBuffers[0].pvBuffer,
513 outBuffers[0].cbBuffer,
514 0
515 );
516 if (n == SOCKET_ERROR || n == 0) {
517 WSAError = WSAGetLastError();
518 FreeContextBuffer(outBuffers[0].pvBuffer);
519 DeleteSecurityContext(&ctxt);
520 ss = SEC_E_INTERNAL_ERROR;
521 break;
522 }
523
524 __DCL_TRACE1(__T("[%d] bytes of Handshake data sent\n"), n);
525 FreeContextBuffer(outBuffers[0].pvBuffer);
526 outBuffers[0].pvBuffer = NULL;
527 }
528 }
529
530 if (ss == SEC_E_INCOMPLETE_MESSAGE) {
531 __DCL_TRACE0(__T("====================== SEC_E_INCOMPLETE_MESSAGE =====================\n"));
532 continue;
533 }
534
535 __DCL_TRACE1(__T("Before OK[%u]\n"), ss);
536 if (ss == SEC_E_OK) {
537 __DCL_TRACE0(__T("Handshake was successful\n"));
538
539 if (inBuffers[1].BufferType == SECBUFFER_EXTRA) {
540 __DCL_TRACE1(__T("Extad data [%d] bytes\n"), inBuffers[1].cbBuffer);
541 }
542
543 break;
544 }
545
546 __DCL_TRACE2(__T("[%u][%ls]\n"), ss, __GetStatusMessage(ss).data());
547
548 if(ss == SEC_I_INCOMPLETE_CREDENTIALS) {
549 __DCL_TRACE0(__T("SEC_I_INCOMPLETE_CREDENTIALS\n"));
550
551 // Get New client Credentials
552
553 break;
554
555 fDoRead = false;
556 ss = SEC_I_CONTINUE_NEEDED;
557 continue;
558 }
559
560 if (inBuffers[1].BufferType == SECBUFFER_EXTRA) {
561 __DCL_TRACE1(__T("Extad data [%d] bytes\n"), inBuffers[1].cbBuffer);
562 memcpy(readBuffer,
563 readBuffer + (nRead - inBuffers[1].cbBuffer),
564 inBuffers[1].cbBuffer
565 );
566 nRead = inBuffers[1].cbBuffer;
567 }
568 else
569 nRead = 0;
570 }
571
572 free(readBuffer);
573
574 if (FAILED(ss)) {
575 DeleteSecurityContext(&ctxt);
576 }
577 else
578 __ctxt = ctxt;
579
580#endif
581}
582
583size_t SSLSocket::send(const void* _buf, size_t _n, int _flags)
585{
586#if __DCL_USE_OPENSSL
587 __DCL_ASSERT_HANDLE(__ctx != NULL);
588 __DCL_ASSERT_HANDLE(__ssl != NULL);
589
590 __DCL_TRACE2(__T("SSLSocket::send(%p, %zd)\n"), _buf, _n);
591
592 int n = (int) _n;
593 int r = SSL_write(__ssl, _buf, (int) _n);
594
595 __DCL_TRACE1(__T("SSLSocket::SSL_write(%d)\n"),r);
596
597 if (r > 0)
598 return (size_t) r;
599
600 switch(SSL_get_error(__ssl, r)) {
601 case SSL_ERROR_NONE:
602 if(n != r)
603 __DCL_TRACE0(__T("Incomplete write!\n"));
604 break;
605 default:
606 throw new IOException(toString(), new SSLException());
607 }
608#endif
609
610 return 0;
611}
612
613size_t SSLSocket::recv(void* _buf, size_t _n, int _flags)
615{
616#if __DCL_USE_OPENSSL
617 __DCL_ASSERT_HANDLE(__ctx != NULL);
618 __DCL_ASSERT_HANDLE(__ssl != NULL);
619
620 __DCL_TRACE2(__T("SSLSocket::recv(%p, %zd)\n"), _buf, _n);
621
622 __DCL_TRACE2(__T("before avail[%zd], pending[%d]\n"),
623 Socket::available(), SSL_pending(__ssl));
624 int n = (int) _n;
625 int r = SSL_read(__ssl, _buf, n);
626 __DCL_TRACE1(__T("SSLSocket::SSL_read(%d)\n"), r);
627 __DCL_TRACE2(__T("after avail[%zd], pending[%d]\n"),
628 Socket::available(), SSL_pending(__ssl));
629 if (r > 0)
630 return (size_t) r;
631
632 switch (SSL_get_error(__ssl, r)) {
633 case SSL_ERROR_ZERO_RETURN:
634 __DCL_TRACE0(__T("SSL error zero return\n"));
635 // ssl close notify, and send close notify
636 SSL_shutdown(__ssl);
637 break;
638 case SSL_ERROR_SYSCALL:
639 __DCL_TRACE0(__T("SSL Error: Premature close\n"));
640 break;
641 default:
642 throw new IOException(toString(), new SSLException());
643 }
644#endif
645 // DWORD dw = SCHANNEL_SHUTDOWN;
646
647 return 0;
648}
649
651{
652#if __DCL_USE_OPENSSL
653 __DCL_ASSERT_HANDLE(__ctx != NULL);
654 __DCL_ASSERT_HANDLE(__ssl != NULL);
655
656 return SSL_get_verify_result(__ssl) !=X509_V_OK;
657#endif
658 return false;
659}
660
662{
663 String s;
664
665#if __DCL_USE_OPENSSL
666 __DCL_ASSERT_HANDLE(__ctx != NULL);
667 __DCL_ASSERT_HANDLE(__ssl != NULL);
668
669 char peer_CN[512];
670
671 X509* peer = SSL_get_peer_certificate(__ssl);
672 if (peer) {
673 int r = X509_NAME_get_text_by_NID(
674 X509_get_subject_name(peer),
675 NID_commonName,
676 peer_CN,
677 sizeof(peer_CN)
678 );
679
680 if (r > 0) {
681 LocaleDecoder decoder;
682 s = decoder.decode(peer_CN);
683 }
684 }
685
686#endif
687 return s;
688}
689
690__DCL_END_NAMESPACE
#define __THIS_FILE__
Definition _trace.h:14
#define NULL
Definition Config.h:340
wchar_t char_t
Definition Config.h:275
#define __DCL_THROWS2(e1, e2)
Definition Config.h:168
#define __DCL_THROWS1(e)
Definition Config.h:167
#define __DCL_TRACE0(psz)
Definition Object.h:375
#define __DCL_TRACE1(fmt, arg1)
Definition Object.h:376
#define __DCL_TRACE3(fmt, arg1, arg2, arg3)
Definition Object.h:378
#define IMPLEMENT_CLASSINFO(class_name, base_class_name)
Definition Object.h:228
#define __T(str)
Definition Object.h:44
#define __DCL_ASSERT_HANDLE(expr)
Definition Object.h:383
#define __DCL_TRACE2(fmt, arg1, arg2)
Definition Object.h:377
ByteString r
ByteBuffer * buf
_r
Definition SQLField.cpp:260
void CharsetConvertException *size_t n
Definition SQLField.cpp:253
virtual String toString() const
Definition Exception.cpp:40
virtual void destroy()
Definition Exception.cpp:74
HandleType __handle
Definition File.h:251
virtual void close() __DCL_THROWS1(IOException *)
Definition File.cpp:363
virtual size_t read(void *_buf, size_t _n) __DCL_THROWS1(IOException *)
Definition File.cpp:476
virtual String toString() const
virtual size_t write(const void *_buf, size_t _n) __DCL_THROWS1(IOException *)
Definition File.cpp:535
virtual size_t available() const __DCL_THROWS1(IOException *)
Definition File.cpp:401
String __message
Definition SSLSocket.h:39
virtual size_t send(const void *_buf, size_t _n, int _flags=0) __DCL_THROWS1(IOException *)
virtual size_t recv(void *_buf, size_t _n, int _flags=0) __DCL_THROWS1(IOException *)
SSLSocket() __DCL_THROWS1(SSLException *)
virtual void close() __DCL_THROWS1(IOException *)
bool isPeerCertificateVerified() const
SSLException *virtual ~SSLSocket()
virtual void connect(const sockaddr *_serv_addr, socklen_t _addrlen) __DCL_THROWS1(IOException *)
void construct() __DCL_THROWS1(SSLException *)
String getPeerCertificateCommonName() const
String toString(unsigned _base=10) const
Definition Numeric.inl:54