#include <FNetHttpIHttpEntity.h>
#include <FNetHttpIHttpProgressEventListener.h>
#include <FBaseSysLog.h>
+#include <FSecurity.h>
#include <FBase_StringConverter.h>
#include <FBaseRt_EventDispatcher.h>
#include <FSecCert_CertService.h>
, __isAlreadyResumed(false)
, __isAlreadyPaused(false)
, __isCertRequiredEventFired(false)
+ , __certificateFlag(HTTP_CV_FLAG_AUTOMATIC)
, __pHttpProgressListener(null)
, __pHttpTransactionUserData(null)
, __pHttpCurl(null)
return r;
}
+result
+_HttpTransactionImpl::Set(_HttpTransactionImpl* pHttpTransactionImpl)
+{
+ result r = E_SUCCESS;
+
+ HttpRequest* pHttpRequest = null;
+ _HttpRequestImpl* pHttpRequestImpl = null;
+ _HttpRequestImpl* pSrcHttpRequestImpl = null;
+
+ ByteBuffer* pRequestBuffer = null;
+ ArrayListT< IHttpTransactionEventListener* > listenerList;
+ Object* pUserObject = null;
+
+ //Sets user object.
+ pUserObject = pHttpTransactionImpl->GetUserObject();
+ __pUserData = pUserObject;
+
+ //Sets event listener.
+ r = listenerList.Construct(*(pHttpTransactionImpl->GetEventListenerList()));
+ SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, null, E_OUT_OF_MEMORY,
+ "[E_OUT_OF_MEMORY] Memory allocation failed.");
+
+ for (int i = 0; i < listenerList.GetCount(); i++)
+ {
+ IHttpTransactionEventListener* pListener = null;
+ r = listenerList.GetAt(i, pListener);
+ SysTryReturn(NID_NET_HTTP, r == E_SUCCESS && pListener != null, null, E_SYSTEM,
+ "[E_SYSTEM] A system error has occurred.");
+
+ r = this->AddHttpTransactionListener(*pListener);
+ SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, null, r,
+ "[%s] Failed to add the HttpTransactionEventListener.", GetErrorMessage(r));
+ }
+
+ __pHttpProgressListener = pHttpTransactionImpl->GetHttpProgressEventListener();
+
+ __enableTransactionReadyToWrite = pHttpTransactionImpl->IsTransactionReadyToWriteEanbled();
+ __timeout = pHttpTransactionImpl->GetTimeout();
+ __certificateId = pHttpTransactionImpl->GetClientCertificate();
+ __isAlreadyResumed = pHttpTransactionImpl->IsAlreadyResumed();
+ __certificateFlag = pHttpTransactionImpl->GetServerCertificateVerification();
+
+ pHttpRequest = pHttpTransactionImpl->GetRequest();
+ SysTryReturn(NID_NET_HTTP, pHttpRequest != null, null, E_SYSTEM,
+ "[E_SYSTEM] An internal error has occurred.");
+
+ pHttpRequestImpl = _HttpRequestImpl::GetInstance(*pHttpRequest);
+ SysTryReturn(NID_NET_HTTP, pHttpRequestImpl != null, null, E_SYSTEM,
+ "[E_SYSTEM] An internal error has occurred.");
+
+ pSrcHttpRequestImpl = _HttpRequestImpl::GetInstance(*__pHttpRequest);
+ SysTryReturn(NID_NET_HTTP, pSrcHttpRequestImpl != null, null, E_SYSTEM,
+ "[E_SYSTEM] An internal error has occurred.");
+
+ //Sets HttpRequest.
+ r = pSrcHttpRequestImpl->Set(pHttpRequestImpl);
+ SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, null, E_SYSTEM,
+ "[E_SYSTEM] An internal error has occurred.");
+
+ pRequestBuffer = pHttpTransactionImpl->GetRequestBuffer();
+ if (pRequestBuffer != null)
+ {
+ //Clear the flag of _HttpRequestImpl
+ pSrcHttpRequestImpl->SetReceivedTransactionReadyToWriteEvent(false);
+
+ r = pSrcHttpRequestImpl->WriteBody(*pRequestBuffer);
+ SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, null, r, "[%s] Failed to write the body.", GetErrorMessage(r));
+
+ SysLog(NID_NET_HTTP, "The __pRequestBuffer is added to the Body.");
+ }
+
+ return r;
+}
+
String
_HttpTransactionImpl::GetDefaultUserAgent(void)
{
SysTryReturnResult(NID_NET_HTTP, r == E_SUCCESS,
E_INVALID_ARG, "Failed to parse the content-length.");
//Set Content-Length
- if (contentLen >= 0)
+ if (contentLen > 0)
{
curl_easy_setopt(pCurl, CURLOPT_POSTFIELDSIZE_LARGE, static_cast< curl_off_t >(contentLen));
SysLog(NID_NET_HTTP, "Set the Content-Length(%lld).", contentLen);
}
+ else if (contentLen == 0)
+ {
+ curl_easy_setopt(pCurl, CURLOPT_POSTFIELDSIZE_LARGE, static_cast< curl_off_t >(contentLen));
+ curl_easy_setopt(pCurl, CURLOPT_COPYPOSTFIELDS, NULL);
+ SysLog(NID_NET_HTTP, "Set the Content-Length(%lld).", contentLen);
+ }
SysLog(NID_NET_HTTP, "The Content-Length is %lld.", contentLen);
}
curl_easy_setopt(pCurl, CURLOPT_LOW_SPEED_TIME, 30L);
}
- //Set default CA path.
- String caPath = _CertService::GetCertificateCrtFilePath();
- SysLog(NID_NET_HTTP, "The CA Path is %ls.", caPath.GetPointer());
+ if (__certificateFlag == HTTP_CV_FLAG_IGNORED)
+ {
+ curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYHOST, 0);
+ SysLog(NID_NET_HTTP, "The server certificate verification is ignored.");
- char* pCaPath = _StringConverter::CopyToCharArrayN(caPath);
- SysTryReturnResult(NID_NET_HTTP, pCaPath != null,
- E_OUT_OF_MEMORY, "Memory allocation failed.");
+ } else
+ {
+ //Set default CA path.
+ String caPath = _CertService::GetCertificateCrtFilePath();
+ SysLog(NID_NET_HTTP, "The CA Path is %ls.", caPath.GetPointer());
- curl_easy_setopt(pCurl, CURLOPT_CAINFO, pCaPath);
- curl_easy_setopt(pCurl, CURLOPT_CAPATH, null);
- delete[] pCaPath;
+ char* pCaPath = _StringConverter::CopyToCharArrayN(caPath);
+ SysTryReturnResult(NID_NET_HTTP, pCaPath != null,
+ E_OUT_OF_MEMORY, "Memory allocation failed.");
+
+ curl_easy_setopt(pCurl, CURLOPT_CAINFO, pCaPath);
+ curl_easy_setopt(pCurl, CURLOPT_CAPATH, null);
+ delete[] pCaPath;
- curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 0);
- curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYHOST, 2);
+ curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_easy_setopt(pCurl, CURLOPT_SSL_VERIFYHOST, 2);
+ }
if (__certificateId >= 0)
{
return r;
}
+int
+_HttpTransactionImpl::GetTimeout(void) const
+{
+ return __timeout;
+}
+
result
_HttpTransactionImpl::SetClientCertificate(int certificateId)
{
return r;
}
+int
+_HttpTransactionImpl::GetClientCertificate(void) const
+{
+ return __certificateId;
+}
+
+result
+_HttpTransactionImpl::SetServerCertificateVerification(NetHttpCertificateVerificationFlag flag)
+{
+ result r = E_SUCCESS;
+
+ SysTryReturnResult(NID_NET_HTTP, __isClosed == false,
+ E_INVALID_STATE, "HttpTransaction[%d] is already closed.", __transactionId);
+
+ SysTryReturnResult(NID_NET_HTTP, __isSubmitted == false,
+ E_INVALID_STATE, "HttpTransaction[%d] is already submitted.", __transactionId);
+
+ __certificateFlag = flag;
+
+ SysLog(NID_NET_HTTP, "Set the flag for certificate verification.[%s].", _HttpUtility::ConvertNetHttpCertificateVerificationFlagToString(flag));
+
+ return r;
+}
+
+NetHttpCertificateVerificationFlag
+_HttpTransactionImpl::GetServerCertificateVerification(void) const
+{
+ return __certificateFlag;
+}
+
_HttpTransactionImpl*
_HttpTransactionImpl::GetInstance(HttpTransaction& httpTransaction)
{
result r = E_SUCCESS;
CURLcode curlCode = CURLE_OK;
+ SysLog(NID_NET_HTTP, "Received OnHttpSslHandshake()");
+
_HttpTransactionUserData* pHttpTransactionUserData = static_cast< _HttpTransactionUserData* >(pUserData);
_HttpTransactionImpl* pHttpTransactionImpl = pHttpTransactionUserData->GetHttpTransactionImpl();
- if (pHttpTransactionImpl->__isAlreadyResumed)
+ if (pHttpTransactionImpl->__isAlreadyResumed || pHttpTransactionImpl->__certificateFlag == HTTP_CV_FLAG_IGNORED)
{
SysLog(NID_NET_HTTP, "Resume the HttpTransaction. Ignore to verify the server cert.");
}
else
{
+ if (pHttpTransactionImpl->__certificateFlag == HTTP_CV_FLAG_MANUAL)
+ {
+ unique_ptr<_HttpSslInfo> pSSLInfo;
+
+ SysLog(NID_NET_HTTP, "The certificate mode is HTTP_CV_FLAG_MANUAL");
+
+ pSSLInfo.reset(new (std::nothrow) _HttpSslInfo(pHttpTransactionUserData->GetSocketFd(), pHttpTransactionImpl->__pHttpTransactionEvent));
+ SysTryReturn(NID_NET_HTTP, pSSLInfo != null, CURLE_SSL_CERTPROBLEM, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
+
+ r = _HttpUtility::SetSslCertInfo(*pSSLInfo);
+ SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, CURLE_SSL_CERTPROBLEM, r, "[%s] Memory allocation failed.", GetErrorMessage(r));
+
+ pSSLInfo.release();
+ }
+
SSL_CTX_set_verify_depth(pSslctx, _HTTP_CERT_VERIFICATION_DEPTH_LIMIT);
SSL_CTX_set_verify(pSslctx, SSL_VERIFY_PEER, _HttpTransactionImpl::OnHttpSslVerify);
}
result r = E_SUCCESS;
int socketFd = -1;
unique_ptr<_HttpSslInfo> pSSLInfo;
+ _HttpSslInfo* pExistSslInfo = null;
int sslIndex = SSL_get_ex_data_X509_STORE_CTX_idx();
SSL* pSsl = (SSL*) X509_STORE_CTX_get_ex_data(pX509ctx, sslIndex);
socketFd = SSL_get_fd(pSsl);
SysLog(NID_NET_HTTP, "The ssl socket is %d.", socketFd);
- X509* pServerCert = null;
+ X509* pSrcServerCert = null;
+ unique_ptr<X509, _X509Deleter> pServerCert;
int depth = X509_STORE_CTX_get_error_depth(pX509ctx);
int error = X509_STORE_CTX_get_error(pX509ctx);
- if (error != X509_V_OK)
+ pExistSslInfo = _HttpUtility::GetSslCertInfo(socketFd);
+
+ if (pExistSslInfo != null)
{
- STACK_OF(X509)* pServerCertChain = null;
+ bool certVerificationResult = false;
+
+ _HttpTransactionEvent* pHttpTransactionEvent = pExistSslInfo->GetHttpTransactionEvent();
+ SysTryReturn(NID_NET_HTTP, pHttpTransactionEvent != null, 0, E_SYSTEM, "[E_SYSTEM] pHttpTransactionEvent must not be null.");
+
+ if (pHttpTransactionEvent->GetCertRequestedResult())
+ {
+ SysLog(NID_NET_HTTP, "The certificate verification is already resumed.");
+ return 1;
+ }
+
+ //The certificateFlag is HTTP_CV_FLAG_MANUAL.
String serverCertString;
- pServerCertChain = X509_STORE_CTX_get1_chain(pX509ctx);
+ STACK_OF(X509)* pSrcServerCertChain = X509_STORE_CTX_get1_chain(pX509ctx);
+ unique_ptr<STACK_OF(X509), _X509ChainDeleter> pServerCertChain(pSrcServerCertChain);
if (pServerCertChain != null)
{
+ unique_ptr<IList, _CollectionDeleter> pCertList(new (nothrow) LinkedList(SingleObjectDeleter));
+ SysTryReturn(NID_NET_HTTP, pCertList != null, 0, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
+
int numberOfCerts = pServerCertChain->stack.num;
for (int i = numberOfCerts; i > 0; i--)
{
- pServerCert = sk_X509_pop(pServerCertChain);
+ pSrcServerCert = sk_X509_pop(pSrcServerCertChain);
+ pServerCert.reset(pSrcServerCert);
if (pServerCert != null)
{
char tempSubjectName[_HTTP_CERT_SUBJECT_SIZE];
- X509_NAME_oneline(X509_get_subject_name(pServerCert), tempSubjectName, _HTTP_CERT_SUBJECT_SIZE);
+ X509_NAME_oneline(X509_get_subject_name(pSrcServerCert), tempSubjectName, _HTTP_CERT_SUBJECT_SIZE);
serverCertString = String(tempSubjectName);
- SysLog(NID_NET_HTTP, "The subject of certificate is %ls[depth: %d].", serverCertString.GetPointer(), i -1);
- depth = i -1;
- X509_free(pServerCert);
+ SysLog(NID_NET_HTTP, "Count of Certs(%d), The subject of certificate is %ls[depth: %d].", numberOfCerts, serverCertString.GetPointer(), i -1);
+
+ // Converter X509 to ByteBuffer.
+ int bufferSize = -1;
+ int len = -1;
+ ByteBuffer buffer;
+ unique_ptr<X509Certificate> pX509Certificate;
+ char* pSrcCertBytes = null;
+ unique_ptr<char, _CharDeleter> pCertBytes;
+
+ BIO* pNewBIoCert = BIO_new(BIO_s_mem());
+ unique_ptr<BIO, _BIoDeleter> pBIoCert(pNewBIoCert);
+ SysTryReturn(NID_NET_HTTP, pBIoCert != null, 0, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
+
+ PEM_write_bio_X509(pNewBIoCert, pSrcServerCert);
+ bufferSize = BIO_number_written(pNewBIoCert);
+
+ pSrcCertBytes = (char*) calloc(bufferSize, sizeof(char));
+ pCertBytes.reset(pSrcCertBytes);
+ SysTryReturn(NID_NET_HTTP, pCertBytes != null, 0, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
+
+ len = BIO_read(pNewBIoCert, pSrcCertBytes, bufferSize);
+ SysLog(NID_NET_HTTP, "The buffer size is %d.", len);
+
+ r = buffer.Construct((byte*)pSrcCertBytes, 0, len, len);
+ SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, 0, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
+ pX509Certificate.reset(new (nothrow) X509Certificate());
+ SysTryReturn(NID_NET_HTTP, pX509Certificate != null, 0, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
+
+ r = pX509Certificate->Construct(buffer);
+ SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, 0, E_SYSTEM, "[E_SYSTEM] Failed to construct X509Certificate.");
+
+ SysLog(NID_NET_HTTP, "Subject: %ls, Issuer: %ls", pX509Certificate->GetSubject().GetPointer(), pX509Certificate->GetIssuer().GetPointer());
+
+ r = pCertList->Add(*pX509Certificate);
+ SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, 0, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
+
+ pX509Certificate.release();
}
}
- sk_X509_free(pServerCertChain);
- }
-
- const char* pErrorMsg = X509_verify_cert_error_string(error);
- SysLog(NID_NET_HTTP, "Failed to verify the cert. depth(%d) - error(%s)", depth, pErrorMsg);
- SysLog(NID_NET_HTTP, "The subject of last certificate is %ls.", serverCertString.GetPointer());
- pSSLInfo.reset(new (std::nothrow) _HttpSslInfo(socketFd, depth, serverCertString, pErrorMsg));
- SysTryReturn(NID_NET_HTTP, pSSLInfo != null, 0, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
+ //Fire the event(_HTTP_TRANSACTION_EVENT_TYPE_CERT_VERIFICATION_REQUESTED)
+ pHttpTransactionEvent->FireTransactionCertVerificationRequestedNEvent(pCertList.release());
- r = _HttpUtility::AddSslCertInfo(*pSSLInfo);
- SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, 0, r, "[%s] Memory allocation failed.", GetErrorMessage(r));
+ certVerificationResult = pHttpTransactionEvent->GetCertRequestedResult();
+ if (certVerificationResult)
+ {
+ _HttpSessionImpl* pHttpSessionImpl = pHttpTransactionEvent->GetHttpSessionImpl();
+ pHttpSessionImpl->IgnoreSslVerification();
+ }
- pSSLInfo.release();
+ //Check the result
+ return pHttpTransactionEvent->GetCertRequestedResult();
+ }
return 0;
- }
- else
+ } else
{
- return 1;
+ // The certificateFlag is HTTP_CV_FLAG_AUTOMATIC.
+ if (error != X509_V_OK)
+ {
+ String serverCertString;
+ STACK_OF(X509)* pSrcServerCertChain = X509_STORE_CTX_get1_chain(pX509ctx);
+ unique_ptr<STACK_OF(X509), _X509ChainDeleter> pServerCertChain(pSrcServerCertChain);
+ if (pServerCertChain != null)
+ {
+ int numberOfCerts = pServerCertChain->stack.num;
+ for (int i = numberOfCerts; i > 0; i--)
+ {
+ pSrcServerCert = sk_X509_pop(pSrcServerCertChain);
+ pServerCert.reset(pSrcServerCert);
+ if (pServerCert != null)
+ {
+ char tempSubjectName[_HTTP_CERT_SUBJECT_SIZE];
+ X509_NAME_oneline(X509_get_subject_name(pSrcServerCert), tempSubjectName, _HTTP_CERT_SUBJECT_SIZE);
+ serverCertString = String(tempSubjectName);
+
+ SysLog(NID_NET_HTTP, "The subject of certificate is %ls[depth: %d].", serverCertString.GetPointer(), i -1);
+ depth = i -1;
+ }
+ }
+ }
+
+ const char* pErrorMsg = X509_verify_cert_error_string(error);
+ SysLog(NID_NET_HTTP, "Failed to verify the cert. depth(%d) - error(%s)", depth, pErrorMsg);
+ SysLog(NID_NET_HTTP, "The subject of last certificate is %ls.", serverCertString.GetPointer());
+
+ pSSLInfo.reset(new (std::nothrow) _HttpSslInfo(socketFd, depth, serverCertString, pErrorMsg));
+ SysTryReturn(NID_NET_HTTP, pSSLInfo != null, 0, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
+
+ r = _HttpUtility::SetSslCertInfo(*pSSLInfo);
+ SysTryReturn(NID_NET_HTTP, r == E_SUCCESS, 0, r, "[%s] Memory allocation failed.", GetErrorMessage(r));
+
+ pSSLInfo.release();
+
+ return 0;
+
+ }
+ else
+ {
+ return 1;
+ }
+
}
}