解析URL的域名證書

可以通過 openssl 獲取常規的,但是部分網站獲取不正確。

// 請使用 CertFreeCertificateContext 釋放 *p_context
void GetCertFromDomain(const wchar_t* domain, int nPort, CERT_CONTEXT** p_context)
{
	if (NULL == domain || NULL == p_context)
	{
		return;
	}
	
	static HINTERNET hsession = NULL;
	HINTERNET hconnect = NULL;
	HINTERNET _request = NULL;
	do
	{
		BOOL bRet = FALSE;
		DWORD dwTime = 5;
		if (NULL == hsession)
		{
			hsession = WinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, 
				WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
		}

		if (NULL == hsession)
		{
			break;
		}

		hconnect = WinHttpConnect(hsession, domain, nPort, 0);
		if (NULL == hconnect)
		{
			break;
		}

		bRet = WinHttpSetTimeouts(hsession, 2000, 2000, 2000, 2000);

		_request = WinHttpOpenRequest(hconnect, NULL, L"/", NULL, WINHTTP_NO_REFERER, 
			WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_REFRESH | WINHTTP_FLAG_SECURE);
		if (NULL == _request)
		{
			break;
		}

		bRet = WinHttpSendRequest(_request,
			WINHTTP_NO_ADDITIONAL_HEADERS,
			0, WINHTTP_NO_REQUEST_DATA, 0,
			0, 0);

		if (bRet)
		{
			DWORD len = 4;
			WCHAR* pBuff = NULL;
			if (!WinHttpQueryOption(_request, WINHTTP_OPTION_SERVER_CERT_CONTEXT,
				&pBuff, &len))
			{
				break;
			}

			*p_context = (CERT_CONTEXT*)pBuff;

			if (!*p_context)
			{
				break;
			}
		}
	} while (0);

	if (_request)
		WinHttpCloseHandle(_request);
	if (hconnect)
		WinHttpCloseHandle(hconnect);
	if (hsession)
		WinHttpCloseHandle(hsession);
}
int main(int argc, char* argv[])
{
	CERT_CONTEXT* p_context = NULL;
	GetCertFromDomain(L"jd.com", 443, &p_context);

	{
		X509* x = NULL;
		GENERAL_NAMES* subjectAltNames = NULL;
		std::list<std::string> lstHosts;
		do
		{
			x = d2i_X509(NULL, (const unsigned char**)&p_context->pbCertEncoded, p_context->cbCertEncoded);
			if (NULL == x)
			{
				break;
			}
			subjectAltNames = (GENERAL_NAMES*)X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
			if (NULL == subjectAltNames)
			{
				break;
			}

			int count = sk_GENERAL_NAME_num(subjectAltNames);
			for (int i = 0; i < count; i++)
			{
				GENERAL_NAME* gen = sk_GENERAL_NAME_value(subjectAltNames, i);
				if (gen->type == GEN_URI || gen->type == GEN_DNS || gen->type == GEN_EMAIL)
				{
					ASN1_IA5STRING* asn1_str = gen->d.uniformResourceIdentifier;
					//	OutputDebugStringA((char*)ASN1_STRING_data(asn1_str));//,ASN1_STRING_length(asn1_str));
					std::string strTmp;
					strTmp.append((char*)ASN1_STRING_data(asn1_str), ASN1_STRING_length(asn1_str));
					lstHosts.push_back(strTmp);
				}
			}

			break;
		} while (0);

		if (subjectAltNames)
		{
			GENERAL_NAMES_free(subjectAltNames);
		}

		if (x)
		{
			X509_free(x);
		}

		CertFreeCertificateContext(p_context);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章