DCL 3.7.4
Loading...
Searching...
No Matches
SSLSocket Class Reference

#include <SSLSocket.h>

Inheritance diagram for SSLSocket:
Socket PollAble File Object

Public Member Functions

 SSLSocket () __DCL_THROWS1(SSLException *)
 SSLSocket (const String &_addr, uint16_t _port) __DCL_THROWS2(IOException *
SSLException *virtual ~SSLSocket ()
virtual void close () __DCL_THROWS1(IOException *)
virtual void connect (const sockaddr *_serv_addr, socklen_t _addrlen) __DCL_THROWS1(IOException *)
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 *)
bool isPeerCertificateVerified () const
String getPeerCertificateCommonName () const
Public Member Functions inherited from File
virtual String toString () const
virtual ~File ()
 File (const String &_path, int _oflags=READONLY, int _mode=0666) __DCL_THROWS1(IOException *)
void open (const String &_path, int _oflags=READONLY, int _mode=0666) __DCL_THROWS1(IOException *)
 File (HandleType _handle, int _ohints, bool _closeOnClose) __DCL_THROWS1(IOException *)
void open (HandleType _handle, int _ohints, bool _closeOnClose) __DCL_THROWS1(IOException *)
virtual void sync () __DCL_THROWS1(IOException *)
off_t seek (off_t _offset, int _whence) __DCL_THROWS1(IOException *)
off_t size () const __DCL_THROWS1(IOException *)
DateTime mtime () const __DCL_THROWS1(IOException *)
bool time (time_t *_atime, time_t *_mtime, time_t *_ctime) const
HandleType handle () const
const String & path () const
Public Member Functions inherited from Object
virtual void destroy ()
String className () const
bool isInstanceOf (const std::type_info &typeinfo) const
virtual const std::type_info & typeInfo () const

Protected Member Functions

void construct () __DCL_THROWS1(SSLException *)
Protected Member Functions inherited from Socket
virtual bool onEvent (short _revents, PollThread *_pPollThread) __DCL_THROWS1(IOException *)
Protected Member Functions inherited from File
 File ()
 File (HandleType _handle, const String &_path)
Protected Member Functions inherited from Object
virtual ~Object ()
 Object ()

Additional Inherited Members

Public Types inherited from File
enum  Whence { BEGIN , CURRENT , END }
Static Public Member Functions inherited from File
static FileopenTempFile (const String &_dirname, const String &_prefix, unsigned int _mode=0666) __DCL_THROWS1(IOException *)
Protected Attributes inherited from File
String __path
HandleType __handle
bool __closeOnClose

Detailed Description

SSL/TLS 소켓에 대한 파일 인터페이스와 Non-Blocking 입출력을 제공한다.

See also
PollThread
SocketPollThread
openssl

Definition at line 49 of file SSLSocket.h.

Constructor & Destructor Documentation

◆ SSLSocket() [1/2]

SSLSocket::SSLSocket ( )

Definition at line 261 of file SSLSocket.cpp.

263{
264 construct();
265}
void construct() __DCL_THROWS1(SSLException *)

◆ SSLSocket() [2/2]

SSLSocket::SSLSocket ( const String & _addr,
uint16_t _port )

◆ ~SSLSocket()

SSLSocket::~SSLSocket ( )
virtual

Definition at line 274 of file SSLSocket.cpp.

275{
276#if __DCL_OPENSSL
277 if (__ssl)
278#elif __DCL_SCHANNEL
279 if (SecIsValidHandle(&__ctxt))
280#endif
281 {
282 try {
283 close();
284 }
285 catch (Exception* cause) {
286 __DCL_TRACE1(__T("Error! SSLSocket::~SSLSocket %ls\n"), cause->toString().data());
287 cause->destroy();
288 }
289 }
290
291#if __DCL_OPENSSL
292 if (__ctx) {
293 SSL_CTX_free(__ctx);
294 #ifdef __DCL_DEBUG
295 __ctx = NULL;
296 #endif
297 }
298
299#elif __DCL_SCHANNEL
300 if (SecIsValidHandle(&__cred)) {
301 SECURITY_STATUS __UNUSED__ ss = FreeCredentialsHandle(&__cred);
302 #ifdef __DCL_DEBUG
303 if (ss != SEC_E_OK)
304 __DCL_TRACE1(__T("Warning!! [%ls]\n"), __GetStatusMessage(ss).data());
305 SecInvalidateHandle(&__cred);
306 #endif
307 }
308
309#endif
310}
#define NULL
Definition Config.h:312
#define __UNUSED__
Definition Config.h:341
#define __DCL_TRACE1(fmt, arg1)
Definition Object.h:399
#define __T(str)
Definition Object.h:60
virtual String toString() const
Definition Exception.cpp:40
virtual void destroy()
Definition Exception.cpp:74
virtual void close() __DCL_THROWS1(IOException *)

Member Function Documentation

◆ close()

void SSLSocket::close ( )
virtual

파일을 닫는다.

Reimplemented from Socket.

Definition at line 312 of file SSLSocket.cpp.

314{
315#if __DCL_OPENSSL
316 __DCL_ASSERT_HANDLE(__ssl != NULL);
317 SSL_free(__ssl);
318 __ssl = NULL;
319
320#elif __DCL_SCHANNEL
321 __DCL_ASSERT_HANDLE(SecIsValidHandle(&__ctxt));
322 SECURITY_STATUS __UNUSED__ ss = DeleteSecurityContext(&__ctxt);
323 #ifdef __DCL_DEBUG
324 if (ss != SEC_E_OK)
325 __DCL_TRACE1(__T("Warning!! [%ls]\n"), __GetStatusMessage(ss).data());
326 #endif
327 SecInvalidateHandle(&__ctxt);
328
329#endif
330
332}
#define __DCL_ASSERT_HANDLE(expr)
Definition Object.h:408
virtual void close() __DCL_THROWS1(IOException *)
Definition File.cpp:369

◆ connect()

void SSLSocket::connect ( const sockaddr * _serv_addr,
socklen_t _addrlen )
virtual

Reimplemented from Socket.

Definition at line 346 of file SSLSocket.cpp.

348{
349 Socket::connect(_serv_addr, _addrlen);
350
351 __DCL_TRACE0(__T("SSLSocket::connect()\n"));
352
353#if __DCL_OPENSSL
354 __DCL_ASSERT_HANDLE(__ctx != NULL);
355 __DCL_ASSERT_HANDLE(__ssl == NULL);
356 __ssl = SSL_new(__ctx);
357 BIO* bio = BIO_new_socket(__handle, BIO_NOCLOSE);
358
359 SSL_set_bio(__ssl, bio, bio);
360
361 if (SSL_connect(__ssl) < 0)
362 throw new IOException(toString(), new SSLException());
363
364#elif __DCL_SCHANNEL
365 DWORD fContextReq = ISC_REQ_SEQUENCE_DETECT
366 | ISC_REQ_REPLAY_DETECT
367 | ISC_REQ_CONFIDENTIALITY
368 | ISC_RET_EXTENDED_ERROR
369 | ISC_REQ_ALLOCATE_MEMORY
370 | ISC_REQ_STREAM;
371
372 SecBufferDesc outBufferDesc;
373 SecBuffer outBuffers[1];
374
375 outBuffers[0].BufferType = SECBUFFER_TOKEN;
376 outBuffers[0].cbBuffer = 0;
377 outBuffers[0].pvBuffer = NULL;
378 outBufferDesc.ulVersion = SECBUFFER_VERSION;
379 outBufferDesc.cBuffers = 1;
380 outBufferDesc.pBuffers = outBuffers;
381
382 CtxtHandle ctxt;
383 ULONG ctxtAttr;
384 TimeStamp tsExpiry;
385
386 SECURITY_STATUS ss = InitializeSecurityContextW(
387 &__cred, // __in PCredHandle phCredential,
388 NULL, // __in_out PCtxtHandle phContext,
389 NULL, // __in SEC_CHAR* pszTargetName,
390 fContextReq, // __in ULONG fContextReq,
391 0, // ULONG Reserved1,
392 0, // __in ULONG TargetDataRep,
393 NULL, // __in_out PSecBufferDesc pInput,
394 0, // ULONG Reserved2,
395 &ctxt, // __in_out PCtxtHandle phNewContext,
396 &outBufferDesc, // __out PSecBufferDesc pOutput,
397 &ctxtAttr, // __out PULONG pfContextAttr,
398 &tsExpiry // __out PTimeStamp ptsExpiry
399 );
400
401 if (FAILED(ss))
402 throw new IOException(toString(), new SSLException(ss));
403
404 __DCL_TRACE1(__T("%ls\n"), __GetStatusMessage(ss).data());
405
406 if (outBuffers[0].cbBuffer != 0 && outBuffers[0].pvBuffer != NULL) {
407 __DCL_TRACE3(__T("%d, %d, [%ls]\n"),
408 outBuffers[0].BufferType,
409 outBuffers[0].cbBuffer,
410 String::tryString((const char*) outBuffers[0].pvBuffer,
411 outBuffers[0].cbBuffer, 8).data()
412 );
413 int n = ::send((UINT_PTR) __handle,
414 (const char*) outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0);
415 if (n == SOCKET_ERROR || n == 0) {
416 FreeContextBuffer(outBuffers[0].pvBuffer);
417 DeleteSecurityContext(&ctxt);
418 throw new IOException(toString(), WSAGetLastError());
419 }
420
421 __DCL_TRACE1(__T("[%d] bytes of Handshake data sent\n"), n);
422 FreeContextBuffer(outBuffers[0].pvBuffer);
423 outBuffers[0].pvBuffer = NULL;
424 }
425
426 // Handshake
427 SecBufferDesc inBufferDesc;
428 SecBuffer inBuffers[2];
429
430 __UNUSED__ DWORD WSAError = 0;
431#define READ_BUFFER_SIZE 0x10000
432 char* readBuffer = (char*) malloc(READ_BUFFER_SIZE);
433 bool fDoRead = true;
434 unsigned int nRead = 0;
435
436 while (ss == SEC_I_CONTINUE_NEEDED
437 || ss == SEC_E_INCOMPLETE_MESSAGE
438 || ss == SEC_I_INCOMPLETE_CREDENTIALS
439 ) {
440 if (0 == nRead || ss == SEC_E_INCOMPLETE_MESSAGE) {
441 if (fDoRead) {
442 int n = ::recv(
443 (UINT_PTR) __handle,
444 readBuffer + nRead,
445 READ_BUFFER_SIZE - nRead,
446 0
447 );
448 if (n == SOCKET_ERROR) {
449 WSAError = WSAGetLastError();
450 ss = SEC_E_INTERNAL_ERROR;
451 break;
452 }
453 else if (n == 0) {
454 WSAError = WSAECONNRESET;
455 ss = SEC_E_INTERNAL_ERROR;
456 break;
457 }
458 __DCL_TRACE2(__T("Handshake read [%d] [%ls]\n"), n,
459 String::tryString((const char*) readBuffer + nRead, n, 8).data());
460
461 nRead += n;
462 }
463 else
464 fDoRead = true;
465 }
466
467 inBuffers[0].BufferType = SECBUFFER_TOKEN;
468 inBuffers[0].cbBuffer = nRead;
469 inBuffers[0].pvBuffer = readBuffer;
470
471 inBuffers[1].BufferType = SECBUFFER_EMPTY;
472 inBuffers[1].cbBuffer = 0;
473 inBuffers[1].pvBuffer = NULL;
474
475 inBufferDesc.ulVersion = SECBUFFER_VERSION;
476 inBufferDesc.cBuffers = 2;
477 inBufferDesc.pBuffers = inBuffers;
478
479 outBuffers[0].BufferType = SECBUFFER_TOKEN;
480 outBuffers[0].cbBuffer = 0;
481 outBuffers[0].pvBuffer = NULL;
482
483 outBufferDesc.ulVersion = SECBUFFER_VERSION;
484 outBufferDesc.cBuffers = 1;
485 outBufferDesc.pBuffers = outBuffers;
486
487 ss = InitializeSecurityContextW(
488 &__cred,
489 &ctxt,
490 NULL,
491 fContextReq,
492 0,
493 SECURITY_NATIVE_DREP,
494 &inBufferDesc,
495 0,
496 NULL,
497 &outBufferDesc,
498 &ctxtAttr,
499 &tsExpiry
500 );
501
502 if (ss == SEC_E_OK
503 || ss == SEC_I_CONTINUE_NEEDED
504 || (FAILED(ss) && (ctxtAttr & ISC_RET_EXTENDED_ERROR))
505 ) {
506 if (outBuffers[0].cbBuffer != 0 && outBuffers[0].pvBuffer != NULL) {
507 int n = ::send(
508 (UINT_PTR) __handle,
509 (const char*) outBuffers[0].pvBuffer,
510 outBuffers[0].cbBuffer,
511 0
512 );
513 if (n == SOCKET_ERROR || n == 0) {
514 WSAError = WSAGetLastError();
515 FreeContextBuffer(outBuffers[0].pvBuffer);
516 DeleteSecurityContext(&ctxt);
517 ss = SEC_E_INTERNAL_ERROR;
518 break;
519 }
520
521 __DCL_TRACE1(__T("[%d] bytes of Handshake data sent\n"), n);
522 FreeContextBuffer(outBuffers[0].pvBuffer);
523 outBuffers[0].pvBuffer = NULL;
524 }
525 }
526
527 if (ss == SEC_E_INCOMPLETE_MESSAGE) {
528 __DCL_TRACE0(__T("====================== SEC_E_INCOMPLETE_MESSAGE =====================\n"));
529 continue;
530 }
531
532 __DCL_TRACE1(__T("Before OK[%u]\n"), ss);
533 if (ss == SEC_E_OK) {
534 __DCL_TRACE0(__T("Handshake was successful\n"));
535 if (inBuffers[1].BufferType == SECBUFFER_EXTRA) {
536 __DCL_TRACE1(__T("Extad data [%d] bytes\n"), inBuffers[1].cbBuffer);
537 }
538 break;
539 }
540
541 __DCL_TRACE2(__T("[%u][%ls]\n"), ss, __GetStatusMessage(ss).data());
542 if(ss == SEC_I_INCOMPLETE_CREDENTIALS) {
543 __DCL_TRACE0(__T("SEC_I_INCOMPLETE_CREDENTIALS\n"));
544
545 // FIXME!! 2026-02-05 작업을 하다 중단된 것 같다!!!
546 // Get New client Credentials
547 break;
548
549 fDoRead = false;
550 ss = SEC_I_CONTINUE_NEEDED;
551 continue;
552 }
553
554 if (inBuffers[1].BufferType == SECBUFFER_EXTRA) {
555 __DCL_TRACE1(__T("Extad data [%d] bytes\n"), inBuffers[1].cbBuffer);
556 memcpy(readBuffer,
557 readBuffer + (nRead - inBuffers[1].cbBuffer),
558 inBuffers[1].cbBuffer
559 );
560 nRead = inBuffers[1].cbBuffer;
561 }
562 else
563 nRead = 0;
564 }
565
566 free(readBuffer);
567 if (FAILED(ss)) {
568 DeleteSecurityContext(&ctxt);
569 }
570 else
571 __ctxt = ctxt;
572
573#endif
574}
#define __DCL_TRACE0(psz)
Definition Object.h:398
#define __DCL_TRACE3(fmt, arg1, arg2, arg3)
Definition Object.h:401
#define __DCL_TRACE2(fmt, arg1, arg2)
Definition Object.h:400
HandleType __handle
Definition File.h:255
virtual String toString() const
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 *)

◆ construct()

void SSLSocket::construct ( )
protected

Definition at line 215 of file SSLSocket.cpp.

217{
218#if __DCL_OPENSSL
219 Thread::once(__opensslOnceControl, __opensslLibraryInit);
220 __ctx = NULL;
221 __ssl = NULL;
222 SSL_CTX* ctx = SSL_CTX_new(SSLv23_method());
223 if (ctx == NULL)
224 throw new SSLException();
225 __ctx = ctx;
226
227#elif __DCL_SCHANNEL
228 SecInvalidateHandle(&__cred);
229 SecInvalidateHandle(&__ctxt);
230
231 CredHandle cred;
232 SCHANNEL_CRED credData;
233 TimeStamp tsExpiry;
234
235 ZeroMemory(&credData, sizeof(credData));
236 credData.dwVersion = SCHANNEL_CRED_VERSION;
237 // Specify the TLS V1.0 (client-side) security protocol.
238 // credData.grbitEnabledProtocols = SP_PROT_TLS1_CLIENT;
239
240 credData.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
241 credData.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
242
243 SECURITY_STATUS ss = AcquireCredentialsHandleW(
244 NULL, // __in SEC_CHAR* pszPrincipal, default principal
245 (LPWSTR) UNISP_NAME_W, // __in SEC_CHAR* pszPackage, for Schannel
246 SECPKG_CRED_OUTBOUND, // __in ULONG fCredentialUse,
247 NULL, // __in PLUID pvLogonID, use the current LOGON id
248 &credData, // __in PVOID pAuthData, protocol-specific data
249 NULL, // __in SEC_GET_KEY_FN pGetKeyFn, default
250 NULL, // __in PVOID pvGetKeyArgument, default
251 &cred, // __out PCredHandle phCredential,
252 &tsExpiry // __out PTimeStamp ptsExpiry
253 );
254 if (ss != SEC_E_OK)
255 throw new SSLException(ss);
256
257 __cred = cred;
258#endif
259}

◆ getPeerCertificateCommonName()

String SSLSocket::getPeerCertificateCommonName ( ) const

Definition at line 654 of file SSLSocket.cpp.

655{
656 String s;
657
658#if __DCL_OPENSSL
659 __DCL_ASSERT_HANDLE(__ctx != NULL);
660 __DCL_ASSERT_HANDLE(__ssl != NULL);
661
662 char peer_CN[512];
663 X509* peer = SSL_get_peer_certificate(__ssl);
664 if (peer) {
665 int r = X509_NAME_get_text_by_NID(
666 X509_get_subject_name(peer),
667 NID_commonName,
668 peer_CN,
669 sizeof(peer_CN)
670 );
671
672 if (r > 0) {
673 LocaleDecoder decoder;
674 s = decoder.decode(peer_CN);
675 }
676 }
677
678#endif
679 return s;
680}
IOException *size_t r
Definition MediaInfo.cpp:82

◆ isPeerCertificateVerified()

bool SSLSocket::isPeerCertificateVerified ( ) const

Definition at line 643 of file SSLSocket.cpp.

644{
645#if __DCL_OPENSSL
646 __DCL_ASSERT_HANDLE(__ctx != NULL);
647 __DCL_ASSERT_HANDLE(__ssl != NULL);
648
649 return SSL_get_verify_result(__ssl) !=X509_V_OK;
650#endif
651 return false;
652}

◆ recv()

size_t SSLSocket::recv ( void * _buf,
size_t _n,
int _flags = 0 )
virtual
Returns
Non-Blocking 상태에서 0을 반환할 수 있다. 이 경우 다시 시도해야 한다.

Reimplemented from Socket.

Definition at line 606 of file SSLSocket.cpp.

608{
609#if __DCL_OPENSSL
610 __DCL_ASSERT_HANDLE(__ctx != NULL);
611 __DCL_ASSERT_HANDLE(__ssl != NULL);
612
613 __DCL_TRACE2(__T("SSLSocket::recv(%p, %zd)\n"), _buf, _n);
614
615 __DCL_TRACE2(__T("before avail[%zd], pending[%d]\n"),
616 Socket::available(), SSL_pending(__ssl));
617 int n = (int) _n;
618 int r = SSL_read(__ssl, _buf, n);
619 __DCL_TRACE1(__T("SSLSocket::SSL_read(%d)\n"), r);
620 __DCL_TRACE2(__T("after avail[%zd], pending[%d]\n"),
621 Socket::available(), SSL_pending(__ssl));
622 if (r > 0)
623 return (size_t) r;
624
625 switch (SSL_get_error(__ssl, r)) {
626 case SSL_ERROR_ZERO_RETURN:
627 __DCL_TRACE0(__T("SSL error zero return\n"));
628 // ssl close notify, and send close notify
629 SSL_shutdown(__ssl);
630 break;
631 case SSL_ERROR_SYSCALL:
632 __DCL_TRACE0(__T("SSL Error: Premature close\n"));
633 break;
634 default:
635 throw new IOException(toString(), new SSLException());
636 }
637#endif
638 // DWORD dw = SCHANNEL_SHUTDOWN;
639
640 return 0;
641}
virtual size_t available() const __DCL_THROWS1(IOException *)
Definition File.cpp:407

◆ send()

size_t SSLSocket::send ( const void * _buf,
size_t _n,
int _flags = 0 )
virtual
Returns
Non-Blocking 상태에서 0을 반환할 수 있다. 이 경우 다시 시도해야 한다.

Reimplemented from Socket.

Definition at line 576 of file SSLSocket.cpp.

578{
579#if __DCL_OPENSSL
580 __DCL_ASSERT_HANDLE(__ctx != NULL);
581 __DCL_ASSERT_HANDLE(__ssl != NULL);
582
583 __DCL_TRACE2(__T("SSLSocket::send(%p, %zd)\n"), _buf, _n);
584
585 int n = (int) _n;
586 int r = SSL_write(__ssl, _buf, (int) _n);
587
588 __DCL_TRACE1(__T("SSLSocket::SSL_write(%d)\n"),r);
589
590 if (r > 0)
591 return (size_t) r;
592
593 switch(SSL_get_error(__ssl, r)) {
594 case SSL_ERROR_NONE:
595 if(n != r)
596 __DCL_TRACE0(__T("Incomplete write!\n"));
597 break;
598 default:
599 throw new IOException(toString(), new SSLException());
600 }
601#endif
602
603 return 0;
604}

The documentation for this class was generated from the following files: