📄 defaultdistrict.c
字号:
/* Copyright 2003-2005, Voltage Security, all rights reserved.
*/
#include "vibe.h"
#include "environment.h"
#include "base.h"
#include "libctx.h"
#include "vsdistrict.h"
#include "derhelp.h"
#include "oidlist.h"
#include "ibe.h"
#include "vtime.h"
#include "errorctx.h"
#include "connectioncache.h"
#include "vtassert.h"
#if VOLT_OS != VOLT_WINDOWS_32
#if VOLT_OS != VOLT_MACOSX
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
#define VOLT_CURL_CONNECTION_TYPE 1000
typedef struct
{
VoltLibCtx *libCtx ;
char *memory;
size_t size;
} VoltMemoryStruct;
static void VOLT_CALLING_CONV CurlDeleteConnection(Pointer connection, VtLibCtx libCtx)
{
CURL* curl = (CURL*) connection;
VT_ASSERT(curl != (CURL*)0);
curl_easy_cleanup (curl);
}
static size_t WriteMemoryCallback (
void *ptr,
size_t size,
size_t nmemb,
void *data
)
{
register int realsize = size * nmemb;
VoltMemoryStruct *mem = (VoltMemoryStruct *)data;
VoltLibCtx *libCtx = mem->libCtx;
VOLT_DECLARE_FNCT_LINE (fnctLine)
VOLT_SET_FNCT_LINE (fnctLine)
mem->memory = (char *)Z2Realloc (mem->memory, mem->size + realsize + 1);
if (mem->memory != (char *)0)
{
Z2Memcpy (&(mem->memory[mem->size]), ptr, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return (realsize);
}
VOLT_LOG_ERROR (
(VtLibCtx)libCtx, VT_ERROR_MEMORY, VT_ERROR_TYPE_PRIMARY, fnctLine,
"WriteMemoryCallback", (char *)0)
return (0);
}
int mDoHTTP (
VoltHttpRequestInfo *requestInfo,
char **response,
int *responseCode,
unsigned char *url,
int allowBadCert,
unsigned char *trustStore,
unsigned long timeOut,
void *appData
)
{
int status, offset;
VoltTransportCtx *transCtx = (VoltTransportCtx *)0;
VoltIdentityObject *idObj = (VoltIdentityObject *)0;
VoltLibCtx *libCtx = (VoltLibCtx *)0;
VtUserPassCollector PasswordCollector = (VtUserPassCollector)0;
VtConnectionCacheCtx connectionCacheCtx = (VtConnectionCacheCtx)0;
int isCachedConnection = 0;
unsigned char *userName = (unsigned char *)0;
unsigned char *password = (unsigned char *)0;
unsigned int userNameLen, passwordLen;
unsigned long timeOutFinal;
unsigned char *postData = (unsigned char *)0;
VoltHttpRequestInfoPost *postInfo = (VoltHttpRequestInfoPost *)0;
CURL *curl = (CURL *)0;
VoltMemoryStruct mem;
char errorBuf[CURL_ERROR_SIZE];
char authString[128];
VOLT_DECLARE_FNCT_LINE (fnctLine)
/* First check the type of request and set some variables accordingly
*/
if (requestInfo->requestType == VOLT_REQUEST_TYPE_GET)
{
libCtx = (VoltLibCtx *)requestInfo->requestData;
}
else
{
postInfo = (VoltHttpRequestInfoPost *)requestInfo->requestData;
transCtx = postInfo->transCtx;
PasswordCollector = transCtx->userPassCtx.UserPassFunction;
idObj = postInfo->idObj;
libCtx = (VoltLibCtx *)(transCtx->voltObject.libraryCtx);
postData = postInfo->postData;
}
mem.libCtx = libCtx;
mem.memory = NULL;
mem.size = 0;
errorBuf[0] = 0;
do
{
VOLT_SET_FNCT_LINE (fnctLine)
status = VtGetLibCtxParam(libCtx, VtLibCtxParamConnectionCacheCtx,
(Pointer*)&connectionCacheCtx);
if ((status != 0) && (status != VT_ERROR_GET_INFO_UNAVAILABLE))
break;
if (connectionCacheCtx != (VtConnectionCacheCtx)0)
{
status = connectionCacheCtx->AcquireConnection(connectionCacheCtx,
VOLT_CURL_CONNECTION_TYPE, (Pointer*)&curl);
if (status == 0)
{
isCachedConnection = 1;
}
else if (status != VT_ERROR_ALL_CONNECTIONS_IN_USE)
{
break;
}
}
if (curl == (CURL*)0)
{
VOLT_SET_FNCT_LINE (fnctLine)
status = -1;
curl = curl_easy_init ();
if (curl == (CURL *)0)
break;
}
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_setopt (
curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
if (status != CURLE_OK)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, 1);
if (status != CURLE_OK)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 1);
if (status != CURLE_OK)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 1);
if (status != CURLE_OK)
break;
#if LIBCURL_VERSION_NUM >= 0x070a00
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
if (status != CURLE_OK)
break;
#endif
VT_ASSERT(curl != (CURL*)0);
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, errorBuf);
if (status != CURLE_OK)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_setopt (curl, CURLOPT_URL, url);
if (status != CURLE_OK)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_setopt (curl, CURLOPT_FILE, (void *)&mem);
if (status != CURLE_OK)
break;
if (postData != (unsigned char *)0)
{
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_setopt (curl, CURLOPT_POSTFIELDS, postData);
if (status != CURLE_OK)
break;
}
/* Set a timeout on curl requests. For this provider the time out value
* will be passed in VtCurlTransportInfo struct.
*/
timeOutFinal = timeOut/1000;
/* In curl setting a time out value of 0 actually disables the time out.
* so in that case set the time out to the minimum possible value.
*/
if (timeOutFinal == 0)
timeOutFinal = 1;
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, timeOutFinal);
if (status != CURLE_OK)
break;
/* Have to do this because curl automatically
* uses a default location
*/
if (trustStore != (unsigned char *)0 )
{
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_setopt (curl, CURLOPT_CAINFO, NULL);
if (status != CURLE_OK)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_setopt (curl, CURLOPT_CAPATH, trustStore);
if (status != CURLE_OK)
break;
}
/* Now we are ready to make the network connection. After we receive
* the response we should see what kind of response it is
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_perform (curl);
if (status == CURLE_RECV_ERROR)
{
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_perform(curl);
}
if (status != CURLE_OK)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_getinfo (curl, CURLINFO_HTTP_CODE, responseCode);
if (status != CURLE_OK)
break;
/* The NTLM authentication is supported by curl only in version
* 7.10.6 or later. Make sure this code is compiled only for
* curl 7.10.6 or later.
*/
#if LIBCURL_VERSION_NUM >= 0x070a0d
/* If the responseCode is 401 it means that server needs to authenticate
* us first in order to fulfill the request. In that case we get the
* authentication information from the password collector function
*/
if (*responseCode == 401)
{
VOLT_SET_FNCT_LINE (fnctLine)
status = PasswordCollector (
libCtx, transCtx->userPassCtx.appData, idObj,
VT_USER_PASS_COLLECTOR_PURPOSE_COLLECT,
&userName, &userNameLen, &password, &passwordLen);
if (status != 0)
break;
/* set the authentication mechanism to be any safe mechanism supported
* by curl because we don't want to pass the authentication information
* in clear over the network.7.10.6
*/
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_setopt (curl, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);
if (status != CURLE_OK)
break;
while (*responseCode == 401)
{
/* build the authntication string first */
offset = 0;
Z2Memcpy (authString, userName, userNameLen);
offset += userNameLen;
authString[offset] = ':';
offset++;
Z2Memcpy (authString + offset, password, passwordLen);
offset += passwordLen;
authString[offset] = 0;
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_setopt (curl, CURLOPT_USERPWD, authString);
if (status != CURLE_OK)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_perform (curl);
if (status != CURLE_OK)
break;
VOLT_SET_FNCT_LINE (fnctLine)
status = curl_easy_getinfo (curl, CURLINFO_HTTP_CODE, responseCode);
if (status != CURLE_OK)
break;
if (*responseCode == 401)
{
VOLT_SET_FNCT_LINE (fnctLine)
status = PasswordCollector (
libCtx, transCtx->userPassCtx.appData, idObj,
VT_USER_PASS_COLLECTOR_PURPOSE_COLLECT_RETRY,
&userName, &userNameLen, &password, &passwordLen);
if (status != 0)
break;
}
}
/* release the password collector data if we successfully collected
* the password. If either one of userName or password is NON-NULL
* we should treat it as a successful password collection.
*/
if ( (userName != (unsigned char *)0) ||
(password != (unsigned char *)0 ) )
{
PasswordCollector (
libCtx, transCtx->userPassCtx.appData, idObj,
VT_USER_PASS_COLLECTOR_PURPOSE_RELEASE,
&userName, &userNameLen, &password, &passwordLen);
}
} /* if response code was 401 */
#else
#warning "The version of curl installed doesn't support NTLM authentication. \
if you use windows style authentication, please update your curl \
to at least version 7.10.6"
#endif
} while (0);
if (curl != (CURL*)0)
{
if (connectionCacheCtx != (VtConnectionCacheCtx)0)
{
curl_easy_reset(curl);
if (isCachedConnection)
{
VOLT_SET_FNCT_LINE (fnctLine)
status = connectionCacheCtx->ReleaseConnection(connectionCacheCtx,
VOLT_CURL_CONNECTION_TYPE, (Pointer*) &curl);
}
else
{
VOLT_SET_FNCT_LINE (fnctLine)
status = connectionCacheCtx->AddConnection(connectionCacheCtx,
VOLT_CURL_CONNECTION_TYPE, (Pointer) curl, CurlDeleteConnection, 0);
if (status == 0)
curl = (CURL*)0;
}
}
if (curl != (CURL*)0)
curl_easy_cleanup (curl);
}
if (status == 0)
{
*response = mem.memory;
return (0);
}
/* If there's an error, translate the curl error to toolkit error
*/
switch (status)
{
case CURLE_URL_MALFORMAT :
case CURLE_URL_MALFORMAT_USER :
case CURLE_COULDNT_RESOLVE_PROXY :
case CURLE_COULDNT_RESOLVE_HOST :
case CURLE_UNSUPPORTED_PROTOCOL :
status = VT_ERROR_URL;
break;
case CURLE_COULDNT_CONNECT :
case CURLE_RECV_ERROR :
status = VT_ERROR_NETWORK_CONNECT;
break;
case CURLE_OPERATION_TIMEOUTED :
status = VT_ERROR_TIMEOUT;
break;
case CURLE_SSL_CONNECT_ERROR :
case CURLE_SSL_PEER_CERTIFICATE :
status = VT_ERROR_DISTRICT_NOT_VERIFIED;
break;
case CURLE_SSL_CACERT:
status = VT_ERROR_CANNOT_VERIFY_CERT;
default:
status = VT_ERROR_DOWNLOAD_FAILURE;
break;
}
VOLT_LOG_ERROR (
(VtLibCtx)libCtx, status, VT_ERROR_TYPE_PRIMARY | VT_ERROR_TYPE_OUTSIDE,
fnctLine, "mDoHTTP", errorBuf)
return status;
}
#endif /* VOLT_OS != VOLT_MACOSX */
#endif /* VOLT_OS != VOLT_WINDOWS_32 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -