SslHandle *NetlibSslConnect(SOCKET s, const char* host, int verify) { /* negotiate SSL session, verify cert, return NULL if failed */ bool res = SSL_library_load(); if (!res) return NULL; SslHandle *ssl = (SslHandle*)mir_calloc(sizeof(SslHandle)); ssl->s = s; res = ClientConnect(ssl, host); if (res && verify) { DWORD dwFlags = 0; if (!host || inet_addr(host) != INADDR_NONE) dwFlags |= 0x00001000; res = VerifyCertificate(ssl, host, dwFlags); } if(res) { return ssl; } else { NetlibSslFree(ssl); return NULL; } }
bool Handshake(StreamSocket* user) { int ret; if (outbound) ret = SSL_connect(sess); else ret = SSL_accept(sess); if (ret < 0) { int err = SSL_get_error(sess, ret); if (err == SSL_ERROR_WANT_READ) { SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE); this->status = ISSL_HANDSHAKING; return true; } else if (err == SSL_ERROR_WANT_WRITE) { SocketEngine::ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_SINGLE_WRITE); this->status = ISSL_HANDSHAKING; return true; } else { CloseSession(); } return false; } else if (ret > 0) { // Handshake complete. VerifyCertificate(); status = ISSL_OPEN; SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE | FD_ADD_TRIAL_WRITE); return true; } else if (ret == 0) { CloseSession(); return true; } return true; }
int CTlsSocket::ContinueHandshake() { m_pOwner->LogMessage(Debug_Verbose, _T("CTlsSocket::ContinueHandshake()")); wxASSERT(m_session); wxASSERT(m_tlsState == handshake); int res = gnutls_handshake(m_session); while (res == GNUTLS_E_AGAIN || res == GNUTLS_E_INTERRUPTED) { if ( gnutls_record_get_direction(m_session) != 1 || !m_canWriteToSocket ) break; res = gnutls_handshake(m_session); } if (!res) { m_pOwner->LogMessage(Debug_Info, _T("TLS Handshake successful")); if (ResumedSession()) m_pOwner->LogMessage(Debug_Info, _T("TLS Session resumed")); const wxString protocol = GetProtocolName(); const wxString keyExchange = GetKeyExchange(); const wxString cipherName = GetCipherName(); const wxString macName = GetMacName(); m_pOwner->LogMessage(Debug_Info, _T("Protocol: %s, Key exchange: %s, Cipher: %s, MAC: %s"), protocol.c_str(), keyExchange.c_str(), cipherName.c_str(), macName.c_str()); res = VerifyCertificate(); if (res != FZ_REPLY_OK) return res; if (m_shutdown_requested) { int error = Shutdown(); if (!error || error != EAGAIN) { CSocketEvent *evt = new CSocketEvent(m_pEvtHandler, this, CSocketEvent::close); CSocketEventDispatcher::Get().SendEvent(evt); } } return FZ_REPLY_OK; } else if (res == GNUTLS_E_AGAIN || res == GNUTLS_E_INTERRUPTED) return FZ_REPLY_WOULDBLOCK; Failure(res, ECONNABORTED); return FZ_REPLY_ERROR; }
int CTlsSocket::ContinueHandshake() { m_pOwner->LogMessage(MessageType::Debug_Verbose, _T("CTlsSocket::ContinueHandshake()")); wxASSERT(m_session); wxASSERT(m_tlsState == TlsState::handshake); int res = gnutls_handshake(m_session); while (res == GNUTLS_E_AGAIN || res == GNUTLS_E_INTERRUPTED) { if (!(gnutls_record_get_direction(m_session) ? m_canWriteToSocket : m_canReadFromSocket)) { break; } res = gnutls_handshake(m_session); } if (!res) { m_pOwner->LogMessage(MessageType::Debug_Info, _T("TLS Handshake successful")); if (ResumedSession()) m_pOwner->LogMessage(MessageType::Debug_Info, _T("TLS Session resumed")); const wxString protocol = GetProtocolName(); const wxString keyExchange = GetKeyExchange(); const wxString cipherName = GetCipherName(); const wxString macName = GetMacName(); m_pOwner->LogMessage(MessageType::Debug_Info, _T("Protocol: %s, Key exchange: %s, Cipher: %s, MAC: %s"), protocol, keyExchange, cipherName, macName); res = VerifyCertificate(); if (res != FZ_REPLY_OK) return res; if (m_shutdown_requested) { int error = Shutdown(); if (!error || error != EAGAIN) { m_pEvtHandler->send_event<CSocketEvent>(this, SocketEventType::close, 0); } } return FZ_REPLY_OK; } else if (res == GNUTLS_E_AGAIN || res == GNUTLS_E_INTERRUPTED) return FZ_REPLY_WOULDBLOCK; Failure(res, true); return FZ_REPLY_ERROR; }
bool Handshake(issl_session* session, StreamSocket* user) { int ret = gnutls_handshake(session->sess); if (ret < 0) { if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) { // Handshake needs resuming later, read() or write() would have blocked. if(gnutls_record_get_direction(session->sess) == 0) { // gnutls_handshake() wants to read() again. session->status = ISSL_HANDSHAKING_READ; ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE); } else { // gnutls_handshake() wants to write() again. session->status = ISSL_HANDSHAKING_WRITE; ServerInstance->SE->ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_SINGLE_WRITE); } } else { user->SetError("Handshake Failed - " + std::string(gnutls_strerror(ret))); CloseSession(session); session->status = ISSL_CLOSING; } return false; } else { // Change the seesion state session->status = ISSL_HANDSHAKEN; VerifyCertificate(session,user); // Finish writing, if any left ServerInstance->SE->ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE | FD_ADD_TRIAL_WRITE); return true; } }
// Returns 1 if handshake succeeded, 0 if it is still in progress, -1 if it failed int Handshake(StreamSocket* user) { int ret = gnutls_handshake(this->sess); if (ret < 0) { if(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) { // Handshake needs resuming later, read() or write() would have blocked. this->status = ISSL_HANDSHAKING; if (gnutls_record_get_direction(this->sess) == 0) { // gnutls_handshake() wants to read() again. SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE); } else { // gnutls_handshake() wants to write() again. SocketEngine::ChangeEventMask(user, FD_WANT_NO_READ | FD_WANT_SINGLE_WRITE); } return 0; } else { user->SetError("Handshake Failed - " + std::string(gnutls_strerror(ret))); CloseSession(); return -1; } } else { // Change the seesion state this->status = ISSL_HANDSHAKEN; VerifyCertificate(); // Finish writing, if any left SocketEngine::ChangeEventMask(user, FD_WANT_POLL_READ | FD_WANT_NO_WRITE | FD_ADD_TRIAL_WRITE); return 1; } }
int CTlsSocket::ContinueHandshake() { m_pOwner->LogMessage(Debug_Verbose, _T("CTlsSocket::ContinueHandshake()")); wxASSERT(m_session); wxASSERT(m_tlsState == handshake); int res = gnutls_handshake(m_session); if (!res) { m_pOwner->LogMessage(Debug_Info, _T("Handshake successful")); if (ResumedSession()) m_pOwner->LogMessage(Debug_Info, _T("Session resumed")); const wxString& cipherName = GetCipherName(); const wxString& macName = GetMacName(); m_pOwner->LogMessage(Debug_Info, _T("Cipher: %s, MAC: %s"), cipherName.c_str(), macName.c_str()); res = VerifyCertificate(); if (res != FZ_REPLY_OK) return res; if (m_shutdown_requested) { int error = Shutdown(); if (!error || error != EAGAIN) { CSocketEvent *evt = new CSocketEvent(m_pEvtHandler, this, CSocketEvent::close); CSocketEventDispatcher::Get().SendEvent(evt); } } return FZ_REPLY_OK; } else if (res == GNUTLS_E_AGAIN || res == GNUTLS_E_INTERRUPTED) return FZ_REPLY_WOULDBLOCK; Failure(res, ECONNABORTED); return FZ_REPLY_ERROR; }
SslHandle* NetlibSslConnect(SOCKET s, const char* host, int verify) { SslHandle *ssl = (SslHandle*)mir_calloc(sizeof(SslHandle)); ssl->s = s; SecInvalidateHandle(&ssl->hContext); DWORD dwFlags = 0; if (!host || inet_addr(host) != INADDR_NONE) dwFlags |= 0x00001000; bool res = SSL_library_init(); if (res) res = ClientConnect(ssl, host); if (res && verify) res = VerifyCertificate(ssl, host, dwFlags); if (!res) { NetlibSslFree(ssl); ssl = NULL; } return ssl; }
DWORD do_low_verify (const char *infile, const char *outfile) { HCRYPTPROV hCryptProv = 0; // CSP handle PCCERT_CONTEXT pUserCert = NULL; // User certificate to be used DWORD ret = 1; FILE *tbs = NULL; BYTE *mem_tbs = NULL; DWORD mem_len = 0; FILE *signature = NULL; BYTE *mem_signature = NULL; DWORD signature_len = 0; HCRYPTMSG hMsg = 0; DWORD cbDecoded; BYTE *pbDecoded; DWORD cbSignerCertInfo; PCERT_INFO pSignerCertInfo; PCCERT_CONTEXT pSignerCertContext; PCERT_INFO pSignerCertificateInfo; HCERTSTORE hStoreHandle = NULL; if (! infile) { fprintf (stderr, "No input file was specified\n"); goto err; } tbs = fopen (infile, "rb"); if (!tbs) { fprintf (stderr, "Cannot open input file\n"); goto err; } mem_len = 0; while (!feof(tbs)) { int r = 0; BYTE tmp[1024]; r = fread (tmp, 1, 1024, tbs); mem_tbs = (BYTE *)realloc (mem_tbs, mem_len+r); memcpy (&mem_tbs[mem_len], tmp, r); mem_len += r; } fclose (tbs); tbs = NULL; if (signature) { signature_len = 0; while (!feof(signature)) { int r = 0; BYTE tmp[1024]; r = fread (tmp, 1, 1024, signature); mem_signature = (BYTE *)realloc (mem_signature , signature_len+r); memcpy (&mem_signature [signature_len], tmp, r); signature_len += r; } fclose (signature); signature = NULL; } //-------------------------------------------------------------------- // Open a message for decoding. hMsg = CryptMsgOpenToDecode( TYPE_DER, // Encoding type. 0, // Flags. 0, // Use the default message type. hCryptProv, // Cryptographic provider. NULL, // Recipient information. NULL); // Stream information. if (hMsg) printf("The message to decode is open. \n"); else{ fprintf (stderr, "OpenToDecode failed"); ret = CSP_GetLastError(); goto err; } //-------------------------------------------------------------------- // Update the message with an encoded blob. // Both pbEncodedBlob, the encoded data, // and cbEnclodeBlob, the length of the encoded data, // must be available. if (CryptMsgUpdate( hMsg, // Handle to the message mem_tbs, // Pointer to the encoded blob mem_len, // Size of the encoded blob TRUE)){ // Last call) printf("The encoded blob has been added to the message. \n"); } else { fprintf (stderr, "Decode MsgUpdate failed"); ret = CSP_GetLastError(); goto err; } //-------------------------------------------------------------------- // Get the size of the content. ret = CryptMsgGetParam( hMsg, // Handle to the message CMSG_CONTENT_PARAM, // Parameter type 0, // Index NULL, // Address for returned info &cbDecoded); // Size of the returned info if (ret) printf("The message parameter (CMSG_CONTENT_PARAM) has been acquired. Message size: %d\n", cbDecoded); else{ fprintf (stderr, "Decode CMSG_CONTENT_PARAM failed"); ret = CSP_GetLastError(); goto err; } //-------------------------------------------------------------------- // Allocate memory. pbDecoded = (BYTE *) malloc(cbDecoded); if (!pbDecoded){ fprintf (stderr, "Decode memory allocation failed"); ret = CSP_GetLastError(); goto err; } //-------------------------------------------------------------------- // Get a pointer to the content. ret = CryptMsgGetParam( hMsg, // Handle to the message CMSG_CONTENT_PARAM, // Parameter type 0, // Index pbDecoded, // Address for returned &cbDecoded); // Size of the returned if (ret) printf("The message param (CMSG_CONTENT_PARAM) updated. Length is %lu.\n",(unsigned long)cbDecoded); else{ fprintf (stderr, "Decode CMSG_CONTENT_PARAM #2 failed"); ret = CSP_GetLastError(); goto err; } //-------------------------------------------------------------------- // Verify the signature. // First, get the signer CERT_INFO from the message. //-------------------------------------------------------------------- // Get the size of memory required. if (! pUserCert) { ret = CryptMsgGetParam( hMsg, // Handle to the message CMSG_SIGNER_CERT_INFO_PARAM, // Parameter type 0, // Index NULL, // Address for returned &cbSignerCertInfo); // Size of the returned if (ret) printf("Try to get user cert. OK. Length %d.\n",cbSignerCertInfo); else { printf("No user certificate found in message.\n"); } } if (pUserCert) { hStoreHandle = CertOpenStore(CERT_STORE_PROV_MEMORY, TYPE_DER, 0, CERT_STORE_CREATE_NEW_FLAG,NULL); if (!hStoreHandle){ printf("Cannot create temporary store in memory."); return CSP_GetLastError(); } if (pUserCert) { ret = CertAddCertificateContextToStore(hStoreHandle, pUserCert, CERT_STORE_ADD_ALWAYS, NULL); pSignerCertInfo = pUserCert->pCertInfo; } else ret = 0; if (!ret){ printf("Cannot add user certificate to store."); return CSP_GetLastError(); } } //-------------------------------------------------------------------- // Allocate memory. if (!pUserCert) { pSignerCertInfo = (PCERT_INFO) malloc(cbSignerCertInfo); if (!pSignerCertInfo){ printf("Verify memory allocation failed"); return CSP_GetLastError(); } } //-------------------------------------------------------------------- // Get the message certificate information (CERT_INFO // structure). if (! pUserCert) { ret = CryptMsgGetParam( hMsg, // Handle to the message CMSG_SIGNER_CERT_INFO_PARAM, // Parameter type 0, // Index pSignerCertInfo, // Address for returned &cbSignerCertInfo); // Size of the returned if (ret) printf("The signer info has been returned. \n"); else{ printf("Verify SIGNER_CERT_INFO #2 failed"); return CSP_GetLastError(); } } //-------------------------------------------------------------------- // Open a certificate store in memory using CERT_STORE_PROV_MSG, // which initializes it with the certificates from the message. if (! hStoreHandle) { hStoreHandle = CertOpenStore( CERT_STORE_PROV_MSG, // Store provider type TYPE_DER, // Encoding type hCryptProv, // Cryptographic provider 0, // Flags hMsg); // Handle to the message if (hStoreHandle) printf("The message certificate store be used for verifying\n"); } if (! hStoreHandle) { printf("Cannot open certificate store form message\n"); return CSP_GetLastError(); } //-------------------------------------------------------------------- // Find the signer's certificate in the store. if(pSignerCertContext = CertGetSubjectCertificateFromStore( hStoreHandle, // Handle to store TYPE_DER, // Encoding type pSignerCertInfo)) // Pointer to retrieved CERT_CONTEXT { DWORD errCode=0; DWORD err; printf("A signer certificate has been retrieved. \n"); err=VerifyCertificate(pSignerCertContext,&errCode); if (err) { printf("Subject cert verification failed: err=%x\n",err); return err; } if (errCode) { printf("Subject cert BAD: errCode=%x\n",errCode); return errCode; } } else { printf("Verify GetSubjectCert failed"); return CSP_GetLastError(); } //-------------------------------------------------------------------- // Use the CERT_INFO from the signer certificate to verify // the signature. pSignerCertificateInfo = pSignerCertContext->pCertInfo; if(CryptMsgControl( hMsg, // Handle to the message 0, // Flags CMSG_CTRL_VERIFY_SIGNATURE, // Control type pSignerCertificateInfo)) // Pointer to the CERT_INFO { printf("\nSignature was VERIFIED.\n"); } else { printf("\nThe signature was NOT VEIFIED.\n"); } if(hStoreHandle) CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_FORCE_FLAG); ret = 0; err: return ret; }
int CTlsSocket::Handshake(const CTlsSocket* pPrimarySocket /*=0*/) { m_pOwner->LogMessage(Debug_Verbose, _T("CTlsSocket::Handshake()")); wxASSERT(m_session); m_tlsState = handshake; if (pPrimarySocket) { // Implicitly trust certificate of primary socket unsigned int cert_list_size; const gnutls_datum_t* const cert_list = gnutls_certificate_get_peers(pPrimarySocket->m_session, &cert_list_size); if (cert_list && cert_list_size) { m_implicitTrustedCert.data = new unsigned char[cert_list[0].size]; memcpy(m_implicitTrustedCert.data, cert_list[0].data, cert_list[0].size); m_implicitTrustedCert.size = cert_list[0].size; } } int res = gnutls_handshake(m_session); if (!res) { m_pOwner->LogMessage(Debug_Info, _T("Handshake successful")); wxString cipherName; const char* cipher = gnutls_cipher_get_name(gnutls_cipher_get(m_session)); if (cipher) cipherName = wxString(cipher, wxConvUTF8); else cipherName = _T("unknown"); wxString macName; const char* mac = gnutls_mac_get_name(gnutls_mac_get(m_session)); if (mac) macName = wxString(mac, wxConvUTF8); else macName = _T("unknown"); m_pOwner->LogMessage(Debug_Info, _T("Cipher: %s, MAC: %s"), cipherName.c_str(), macName.c_str()); res = VerifyCertificate(); if (res != FZ_REPLY_OK) return res; m_tlsState = conn; wxSocketEvent evt(GetId()); evt.m_event = wxSOCKET_CONNECTION; wxPostEvent(m_pEvtHandler, evt); TriggerEvents(); if (m_shutdown_requested) { Shutdown(); if (!Error() || LastError() != wxSOCKET_WOULDBLOCK) { wxSocketEvent evt(GetId()); evt.m_event = wxSOCKET_LOST; wxPostEvent(m_pEvtHandler, evt); } } return FZ_REPLY_OK; } else if (res == GNUTLS_E_AGAIN || res == GNUTLS_E_INTERRUPTED) return FZ_REPLY_WOULDBLOCK; Failure(res); return FZ_REPLY_ERROR; }