|
@@ -29,13 +29,6 @@ This class only has a couple of public functions:
|
|
|
You can call this function only after receiving a layerspecific callback with the SSL_VERIFY_CERT
|
|
|
id. Set result to 1 if you trust the certificate and 0 if you don't trust it.
|
|
|
nID has to be the priv_data element of the t_SslCertData structure and nCode has to be SSL_VERIFY_CERT.
|
|
|
-- CreateSslCertificate(LPCTSTR filename, int bits, unsigned char* country, unsigned char* state,
|
|
|
- unsigned char* locality, unsigned char* organization, unsigned char* unit, unsigned char* cname,
|
|
|
- unsigned char *email, CString& err);
|
|
|
- Creates a new self-signed SSL certificate and stores it in the given file
|
|
|
-- SendRaw(const void* lpBuf, int nBufLen, int nFlags = 0)
|
|
|
- Sends a raw, unencrypted message. This may be useful after successful initialization to tell the other
|
|
|
- side that can use SSL.
|
|
|
|
|
|
This layer sends some layerspecific notifications to your socket instance, you can handle them in
|
|
|
OnLayerCallback of your socket class.
|
|
@@ -2149,234 +2142,6 @@ void CAsyncSslSocketLayer::PrintLastErrorMsg()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-bool CAsyncSslSocketLayer::CreateSslCertificate(LPCTSTR filename, int bits, unsigned char* country, unsigned char* state,
|
|
|
- unsigned char* locality, unsigned char* organization, unsigned char* unit, unsigned char* cname,
|
|
|
- unsigned char *email, CString& err)
|
|
|
-{
|
|
|
- // Certificate valid for a year
|
|
|
- int days = 365;
|
|
|
-
|
|
|
- CAsyncSslSocketLayer layer;
|
|
|
- if (layer.InitSSL())
|
|
|
- {
|
|
|
- err = _T("Failed to initialize TLS library");
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- X509 *x;
|
|
|
- EVP_PKEY *pk;
|
|
|
- RSA *rsa;
|
|
|
- X509_NAME *name = NULL;
|
|
|
-
|
|
|
- if ((pk = pEVP_PKEY_new()) == NULL)
|
|
|
- {
|
|
|
- err = _T("Could not create key object");
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if ((x = pX509_new()) == NULL)
|
|
|
- {
|
|
|
- err = _T("Could not create certificate object");
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- rsa = pRSA_generate_key(bits, RSA_F4, 0/*callback*/, NULL);
|
|
|
-
|
|
|
- if (!pEVP_PKEY_assign(pk, EVP_PKEY_RSA, (char *)(rsa)))
|
|
|
- {
|
|
|
- err = _T("Failed to assign rsa key to key object");
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- rsa = NULL;
|
|
|
-
|
|
|
- pX509_set_version(x,2);
|
|
|
- pASN1_INTEGER_set(pX509_get_serialNumber(x), 0/*serial*/);
|
|
|
- pX509_gmtime_adj(X509_get_notBefore(x),0);
|
|
|
- pX509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days);
|
|
|
- pX509_set_pubkey(x,pk);
|
|
|
-
|
|
|
- name = pX509_get_subject_name(x);
|
|
|
-
|
|
|
- /* This function creates and adds the entry, working out the
|
|
|
- * correct string type and performing checks on its length.
|
|
|
- * Normally we'd check the return value for errors...
|
|
|
- */
|
|
|
- pX509_NAME_add_entry_by_txt(name, "CN",
|
|
|
- MBSTRING_ASC, cname, -1, -1, 0);
|
|
|
- pX509_NAME_add_entry_by_txt(name, "C",
|
|
|
- MBSTRING_ASC, country, -1, -1, 0);
|
|
|
- pX509_NAME_add_entry_by_txt(name, "ST",
|
|
|
- MBSTRING_ASC, state, -1, -1, 0);
|
|
|
- pX509_NAME_add_entry_by_txt(name, "L",
|
|
|
- MBSTRING_ASC, locality, -1, -1, 0);
|
|
|
- pX509_NAME_add_entry_by_txt(name, "O",
|
|
|
- MBSTRING_ASC, organization, -1, -1, 0);
|
|
|
- pX509_NAME_add_entry_by_txt(name, "OU",
|
|
|
- MBSTRING_ASC, unit, -1, -1, 0);
|
|
|
- pX509_NAME_add_entry_by_NID(name, NID_pkcs9_emailAddress,
|
|
|
- MBSTRING_ASC, email, -1, -1, 0);
|
|
|
-
|
|
|
- /* Its self signed so set the issuer name to be the same as the
|
|
|
- * subject.
|
|
|
- */
|
|
|
- pX509_set_issuer_name(x,name);
|
|
|
-
|
|
|
- if (!pX509_sign(x, pk, pEVP_sha1()))
|
|
|
- {
|
|
|
- err = _T("Failed to sign certificate");
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- // Write key and certificate to file
|
|
|
- // We use a memory bio, since the OpenSSL functions accepting a filepointer
|
|
|
- // do crash for no obvious reason.
|
|
|
-
|
|
|
-#ifndef _UNICODE
|
|
|
- FILE* file = fopen(filename, "w+");
|
|
|
-#else
|
|
|
- FILE* file = _wfopen(filename, _T("w+"));
|
|
|
-#endif
|
|
|
-
|
|
|
- if (!file)
|
|
|
- {
|
|
|
- err = _T("Failed to open output file");
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- BIO* bio = pBIO_new(pBIO_s_mem());
|
|
|
-#ifdef MPEXT
|
|
|
- pPEM_ASN1_write_bio((i2d_of_void*)pi2d_PrivateKey, (((pk)->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA), bio, (char *)pk, NULL, NULL, 0, NULL, NULL);
|
|
|
- pPEM_ASN1_write_bio((i2d_of_void*)pi2d_X509, PEM_STRING_X509, bio, (char *)x, NULL, NULL, 0, NULL, NULL);
|
|
|
-#else
|
|
|
- pPEM_ASN1_write_bio((int (*)())pi2d_PrivateKey, (((pk)->type == EVP_PKEY_DSA)?PEM_STRING_DSA:PEM_STRING_RSA), bio, (char *)pk, NULL, NULL, 0, NULL, NULL);
|
|
|
- pPEM_ASN1_write_bio((int (*)())pi2d_X509, PEM_STRING_X509, bio, (char *)x, NULL, NULL, 0, NULL, NULL);
|
|
|
-#endif
|
|
|
-
|
|
|
- char buffer[1001];
|
|
|
- int len;
|
|
|
- while ((len = pBIO_read(bio, buffer, 1000)) > 0)
|
|
|
- {
|
|
|
- buffer[len] = 0;
|
|
|
- fprintf(file, buffer);
|
|
|
- }
|
|
|
-
|
|
|
- fclose(file);
|
|
|
-
|
|
|
- pX509_free(x);
|
|
|
- pEVP_PKEY_free(pk);
|
|
|
-
|
|
|
- pBIO_free(bio);
|
|
|
-
|
|
|
- layer.UnloadSSL();
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-int CAsyncSslSocketLayer::SetCertKeyFile(const char* cert, const char* key, const char* pass, CString* error /*=0*/)
|
|
|
-{
|
|
|
- int res = InitSSL();
|
|
|
- if (res)
|
|
|
- return res;
|
|
|
-
|
|
|
- m_sCriticalSection.Lock();
|
|
|
-
|
|
|
- if (!m_ssl_ctx)
|
|
|
- {
|
|
|
- // Create new context
|
|
|
- if (!(m_ssl_ctx = pSSL_CTX_new( pSSLv23_method())))
|
|
|
- {
|
|
|
- m_sCriticalSection.Unlock();
|
|
|
- return SSL_FAILURE_INITSSL;
|
|
|
- }
|
|
|
- m_contextRefCount[m_ssl_ctx] = 1;
|
|
|
- }
|
|
|
-
|
|
|
- pSSL_CTX_set_default_passwd_cb(m_ssl_ctx, pem_passwd_cb);
|
|
|
- pSSL_CTX_set_default_passwd_cb_userdata(m_ssl_ctx, this);
|
|
|
-
|
|
|
- if (pass)
|
|
|
- {
|
|
|
- size_t len = strlen(pass);
|
|
|
- m_pKeyPassword = new char[len + 1];
|
|
|
- strcpy(m_pKeyPassword, pass);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- delete [] m_pKeyPassword;
|
|
|
- m_pKeyPassword = 0;
|
|
|
- }
|
|
|
-
|
|
|
- if (pSSL_CTX_use_certificate_chain_file(m_ssl_ctx, cert) <= 0)
|
|
|
- //if (pSSL_CTX_use_certificate_file(m_ssl_ctx, cert, SSL_FILETYPE_PEM) <= 0)
|
|
|
- {
|
|
|
- if (error)
|
|
|
- *error = _T("Could not load certificate file.");
|
|
|
- m_sCriticalSection.Unlock();
|
|
|
- return SSL_FAILURE_VERIFYCERT;
|
|
|
- }
|
|
|
-
|
|
|
- if (pSSL_CTX_use_PrivateKey_file(m_ssl_ctx, key, SSL_FILETYPE_PEM) <= 0)
|
|
|
- {
|
|
|
- if (error)
|
|
|
- *error = _T("Could not load key file.");
|
|
|
- m_sCriticalSection.Unlock();
|
|
|
- return SSL_FAILURE_VERIFYCERT;
|
|
|
- }
|
|
|
-
|
|
|
- if (!pSSL_CTX_check_private_key(m_ssl_ctx))
|
|
|
- {
|
|
|
- if (error)
|
|
|
- *error = _T("Private key does not match the certificate public key.");
|
|
|
- m_sCriticalSection.Unlock();
|
|
|
- return SSL_FAILURE_VERIFYCERT;
|
|
|
- }
|
|
|
-
|
|
|
- m_sCriticalSection.Unlock();
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-int CAsyncSslSocketLayer::SendRaw(const void* lpBuf, int nBufLen, int nFlags)
|
|
|
-{
|
|
|
- if (!m_bUseSSL)
|
|
|
- {
|
|
|
- SetLastError(WSANOTINITIALISED);
|
|
|
- return SOCKET_ERROR;
|
|
|
- }
|
|
|
-
|
|
|
- if (!lpBuf)
|
|
|
- return 0;
|
|
|
-
|
|
|
- if (m_nNetworkError)
|
|
|
- {
|
|
|
- SetLastError(m_nNetworkError);
|
|
|
- return SOCKET_ERROR;
|
|
|
- }
|
|
|
- if (m_nShutDown)
|
|
|
- {
|
|
|
- SetLastError(WSAESHUTDOWN);
|
|
|
- return SOCKET_ERROR;
|
|
|
- }
|
|
|
- if (m_nNetworkSendBufferLen)
|
|
|
- {
|
|
|
- SetLastError(WSAEINPROGRESS);
|
|
|
- return SOCKET_ERROR;
|
|
|
- }
|
|
|
- if (!nBufLen)
|
|
|
- return 0;
|
|
|
-
|
|
|
- if (m_nNetworkSendBufferMaxLen < nBufLen)
|
|
|
- m_nNetworkSendBufferMaxLen = nBufLen;
|
|
|
- delete [] m_pNetworkSendBuffer;
|
|
|
- m_pNetworkSendBuffer = new char[m_nNetworkSendBufferMaxLen];
|
|
|
- memcpy(m_pNetworkSendBuffer, lpBuf, nBufLen);
|
|
|
- m_nNetworkSendBufferLen = nBufLen;
|
|
|
- TriggerEvent(FD_WRITE, 0);
|
|
|
-
|
|
|
- return nBufLen;
|
|
|
-}
|
|
|
-
|
|
|
void CAsyncSslSocketLayer::TriggerEvents()
|
|
|
{
|
|
|
size_t pending = pBIO_ctrl_pending(m_nbio);
|