使用纯 C 通过 SSL (HTTPS) 进行 WinInet POST?

发布于 2024-07-25 04:43:44 字数 4016 浏览 4 评论 0原文

我一直在尝试仅使用 C 通过 SSL 获取 WinInet HTTP POST。我知道这是可能的。 有好的示例代码吗?

非常感谢!

编辑:以下代码似乎在使用 WinHTTP 的 C++ 下工作正常,但我需要 WinInet:

TCHAR szTemp[512] = {0};
BOOL bRet = FALSE;
HINTERNET hRequest = NULL;
HINTERNET hSession = NULL;
HINTERNET hConnect = NULL;
CERT_CONTEXT *pCert = {0};
HCERTSTORE hCertStore = NULL;
DWORD dwRet = 0;
DWORD dwLen = 0;
DWORD dwFlags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID|
                SECURITY_FLAG_IGNORE_CERT_DATE_INVALID|
                SECURITY_FLAG_IGNORE_UNKNOWN_CA;

CString szUserAgent("Mozilla/4.0 (compatible; MSIE 5.22)");

if ( m_csServer.GetLength() < 3 ) {
    _stprintf_s( szTemp, 512, _T("Server name is invalid or empty") );
    ::MessageBox(NULL, szTemp, _T("ERROR"), MB_OK );
    return;
}

hSession = WinHttpOpen(szUserAgent,
    WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
    WINHTTP_NO_PROXY_NAME,
    WINHTTP_NO_PROXY_BYPASS, 0 );

if ( NULL == hSession ) {
    dwRet = GetLastError();
    _stprintf_s( szTemp, 512, _T("WinHttpOpen Fails - err: 0x%x"), dwRet );
    ::MessageBox(NULL, szTemp, _T("ERROR"), MB_OK );
    return;
}

hConnect = WinHttpConnect( hSession,
    m_csServer,
    INTERNET_DEFAULT_HTTPS_PORT,
    0 );

if ( NULL == hConnect ) {
    dwRet = GetLastError();
    _stprintf_s( szTemp, 512, _T("WinHttpConnect Fails - err: 0x%x"), dwRet );
    ::MessageBox(NULL, szTemp, _T("ERROR"), MB_OK );
    WinHttpCloseHandle( hSession );
    return;
}

hRequest = WinHttpOpenRequest( hConnect,
    L"GET",
    L"",
    NULL,
    WINHTTP_NO_REFERER,
    WINHTTP_DEFAULT_ACCEPT_TYPES,
    WINHTTP_FLAG_SECURE ); 

if ( NULL == hConnect ) {
    dwRet = GetLastError();
    _stprintf_s( szTemp, 512, _T("WinHttpOpenRequest Fails - err: 0x%x"), dwRet );
    ::MessageBox(NULL, szTemp, _T("ERROR"), MB_OK );
    WinHttpCloseHandle( hConnect );
    WinHttpCloseHandle( hSession );
    return;
}

bRet = WinHttpSetOption(
    hRequest,
    WINHTTP_OPTION_SECURITY_FLAGS,
    &dwFlags,
    sizeof(DWORD)
);

if ( FALSE == bRet ) {
    dwRet = GetLastError();
    _stprintf_s( szTemp, 512, _T("WinHttpSetOption Fails - err: 0x%x"), dwRet );
    ::MessageBox(NULL, szTemp, _T("ERROR"), MB_OK );
    WinHttpCloseHandle( hConnect );
    WinHttpCloseHandle( hSession );
    return;
}

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

if ( FALSE == bRet ) {
    dwRet = GetLastError();
    _stprintf_s( szTemp, 512, _T("WinHttpSendRequest Fails - err: 0x%x"), dwRet );
    ::MessageBox(NULL, szTemp, _T("ERROR"), MB_OK );
    WinHttpCloseHandle( hRequest );
    WinHttpCloseHandle( hConnect );
    WinHttpCloseHandle( hSession );
    return;
}

dwLen = sizeof(pCert);

bRet = WinHttpQueryOption(
    hRequest,
    WINHTTP_OPTION_SERVER_CERT_CONTEXT,
    &pCert,
    &dwLen
);

if ( pCert ) {
    if ( pCert->dwCertEncodingType & X509_ASN_ENCODING ) {
        OutputDebugString( _T("X509_ASN_ENCODING") );
    }
    if ( pCert->dwCertEncodingType & PKCS_7_ASN_ENCODING ) {
        OutputDebugString( _T("PKCS_7_ASN_ENCODING") );
    }

    _stprintf_s( szTemp, 512, _T("encoded_size: %ld"), pCert->cbCertEncoded );
    OutputDebugString( szTemp );

    hCertStore = CertOpenStore( CERT_STORE_PROV_SYSTEM, 0, 0, CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE, L"Root"); 

    bRet =  CertAddCertificateContextToStore(
        hCertStore,
        pCert,
        CERT_STORE_ADD_REPLACE_EXISTING,
        NULL
    );

    CertFreeCertificateContext(pCert);

    bRet = CertCloseStore( hCertStore, 0 );

    ::MessageBox( NULL, _T("Certificate Added to Store"), _T("Registered"), MB_OK );

    OutputDebugString ( _T("closed store") );
}
else {
    dwRet = GetLastError();
    _stprintf_s( szTemp, 512, _T("WinHttpQueryOption Fails - err: 0x%x"), dwRet );
    ::MessageBox(NULL, szTemp, _T("ERROR"), MB_OK );
}

WinHttpCloseHandle( hRequest );  
WinHttpCloseHandle( hConnect );
WinHttpCloseHandle( hSession );

I'm stuck trying to get a WinInet HTTP POST via SSL using ONLY C. I know it's possible.
Any good sample code?

Thanks so much!

EDIT: the following code seems to be working OK under C++ using WinHTTP but I need WinInet:

TCHAR szTemp[512] = {0};
BOOL bRet = FALSE;
HINTERNET hRequest = NULL;
HINTERNET hSession = NULL;
HINTERNET hConnect = NULL;
CERT_CONTEXT *pCert = {0};
HCERTSTORE hCertStore = NULL;
DWORD dwRet = 0;
DWORD dwLen = 0;
DWORD dwFlags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID|
                SECURITY_FLAG_IGNORE_CERT_DATE_INVALID|
                SECURITY_FLAG_IGNORE_UNKNOWN_CA;

CString szUserAgent("Mozilla/4.0 (compatible; MSIE 5.22)");

if ( m_csServer.GetLength() < 3 ) {
    _stprintf_s( szTemp, 512, _T("Server name is invalid or empty") );
    ::MessageBox(NULL, szTemp, _T("ERROR"), MB_OK );
    return;
}

hSession = WinHttpOpen(szUserAgent,
    WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
    WINHTTP_NO_PROXY_NAME,
    WINHTTP_NO_PROXY_BYPASS, 0 );

if ( NULL == hSession ) {
    dwRet = GetLastError();
    _stprintf_s( szTemp, 512, _T("WinHttpOpen Fails - err: 0x%x"), dwRet );
    ::MessageBox(NULL, szTemp, _T("ERROR"), MB_OK );
    return;
}

hConnect = WinHttpConnect( hSession,
    m_csServer,
    INTERNET_DEFAULT_HTTPS_PORT,
    0 );

if ( NULL == hConnect ) {
    dwRet = GetLastError();
    _stprintf_s( szTemp, 512, _T("WinHttpConnect Fails - err: 0x%x"), dwRet );
    ::MessageBox(NULL, szTemp, _T("ERROR"), MB_OK );
    WinHttpCloseHandle( hSession );
    return;
}

hRequest = WinHttpOpenRequest( hConnect,
    L"GET",
    L"",
    NULL,
    WINHTTP_NO_REFERER,
    WINHTTP_DEFAULT_ACCEPT_TYPES,
    WINHTTP_FLAG_SECURE ); 

if ( NULL == hConnect ) {
    dwRet = GetLastError();
    _stprintf_s( szTemp, 512, _T("WinHttpOpenRequest Fails - err: 0x%x"), dwRet );
    ::MessageBox(NULL, szTemp, _T("ERROR"), MB_OK );
    WinHttpCloseHandle( hConnect );
    WinHttpCloseHandle( hSession );
    return;
}

bRet = WinHttpSetOption(
    hRequest,
    WINHTTP_OPTION_SECURITY_FLAGS,
    &dwFlags,
    sizeof(DWORD)
);

if ( FALSE == bRet ) {
    dwRet = GetLastError();
    _stprintf_s( szTemp, 512, _T("WinHttpSetOption Fails - err: 0x%x"), dwRet );
    ::MessageBox(NULL, szTemp, _T("ERROR"), MB_OK );
    WinHttpCloseHandle( hConnect );
    WinHttpCloseHandle( hSession );
    return;
}

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

if ( FALSE == bRet ) {
    dwRet = GetLastError();
    _stprintf_s( szTemp, 512, _T("WinHttpSendRequest Fails - err: 0x%x"), dwRet );
    ::MessageBox(NULL, szTemp, _T("ERROR"), MB_OK );
    WinHttpCloseHandle( hRequest );
    WinHttpCloseHandle( hConnect );
    WinHttpCloseHandle( hSession );
    return;
}

dwLen = sizeof(pCert);

bRet = WinHttpQueryOption(
    hRequest,
    WINHTTP_OPTION_SERVER_CERT_CONTEXT,
    &pCert,
    &dwLen
);

if ( pCert ) {
    if ( pCert->dwCertEncodingType & X509_ASN_ENCODING ) {
        OutputDebugString( _T("X509_ASN_ENCODING") );
    }
    if ( pCert->dwCertEncodingType & PKCS_7_ASN_ENCODING ) {
        OutputDebugString( _T("PKCS_7_ASN_ENCODING") );
    }

    _stprintf_s( szTemp, 512, _T("encoded_size: %ld"), pCert->cbCertEncoded );
    OutputDebugString( szTemp );

    hCertStore = CertOpenStore( CERT_STORE_PROV_SYSTEM, 0, 0, CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE, L"Root"); 

    bRet =  CertAddCertificateContextToStore(
        hCertStore,
        pCert,
        CERT_STORE_ADD_REPLACE_EXISTING,
        NULL
    );

    CertFreeCertificateContext(pCert);

    bRet = CertCloseStore( hCertStore, 0 );

    ::MessageBox( NULL, _T("Certificate Added to Store"), _T("Registered"), MB_OK );

    OutputDebugString ( _T("closed store") );
}
else {
    dwRet = GetLastError();
    _stprintf_s( szTemp, 512, _T("WinHttpQueryOption Fails - err: 0x%x"), dwRet );
    ::MessageBox(NULL, szTemp, _T("ERROR"), MB_OK );
}

WinHttpCloseHandle( hRequest );  
WinHttpCloseHandle( hConnect );
WinHttpCloseHandle( hSession );

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文