microsoft / cpprestsdk

The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services.
Other
7.96k stars 1.65k forks source link

REST API C++ - HTTPS Certificate option #199

Open shivendra6782 opened 8 years ago

shivendra6782 commented 8 years ago

Hi,

I have used below code using WinHTTP to use certificate, but now I moved to CPPRESTSDK and want to set the certificate for HTTPS but I am not getting any option in REST API. or its automatically verified when using HTTPS connection and set_validate_certificates(true); Please suggest if my understanding is correct or not.

OS- Windows hRequest = WinHttpOpenRequest(hConnect, L"POST", L"/auth", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, NULL); //WINHTTP_FLAG_SECURE); /_hRequest = WinHttpOpenRequest(hConnect, L"POST", L"/auth", L"HTTP/1.1", WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_REFRESH); WINHTTP_FLAGSECURE);/ if (!hRequest) { Clog::traceLog(ERRORLOG, "WinHttpOpenRequest:Error %d has occurred.", GetLastError()); iRetVal = SDP_ERROR_WINHTTP_INTERNAL_ERROR; } else { hMyStore = CertOpenSystemStore(0, TEXT("MY")); if (hMyStore) { pCertContext = CertFindCertificateInStore(hMyStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, (LPVOID)szCertName, //Subject string in the certificate. NULL); if (!pCertContext) { WinHttpSetOption(hRequest, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, (LPVOID)pCertContext, sizeof(CERT_CONTEXT)); CertFreeCertificateContext(pCertContext); } CertCloseStore(hMyStore, 0);

Thanks, Shivendra

lg29sid commented 8 years ago

I am also looking for the same. In addition to this, I want to which SSL protocol http_client in REST uses to make HTTPS request, is it configurable?

Any help would be much appreciated.

megaposer commented 8 years ago

In order to use a specific client certificate, you need to tie into the native handle callback provided by the C++ REST SDK.

To do so, add a callback to your _web::http::http_clientconfig object via .set_nativehandle_options, using the following signature: void (const web::http::client::native_handle).

Within the callback perform the operations you need to acquire the certificate context, etc. and then use WinHttpSetOption to set the client context as you've already did in your original code.

mostafa88 commented 7 years ago

I also use a http_client_config object and set_validate_certificate(false) to test https request. but it not work and return exception with code 12175, "A security error occurred". I use VS 2013 to build restsdk to run my code on windows 7.

shivendra6782 commented 7 years ago

In prod we need to use below one:

http_client_config config; config.set_validate_certificates(true); http_client client(url, config);

In QA and dev as we have self signed certificate:

http_client_config config; config.set_validate_certificates(false); http_client client(url, config);

This code is working fine. Please share your code if you are still getting this issue.

Thanks, Shivendra

mostafa88 commented 7 years ago

Hi shivendra, thanks for your attention. We also use the mentioned code snipet, with set_validate_certificate(true), and (false). But in both case it retrun the following error in Windows platform. 12175, a security error occured. Does ssl cerificate handling implemented for Windows platform?

On Aug 8, 2017 2:09 AM, "shivendra6782" notifications@github.com wrote:

In prod we need to use below one:

http_client_config config; config.set_validate_certificates(true); http_client client(url, config);

In QA and dev as we have self signed certificate:

http_client_config config; config.set_validate_certificates(false); http_client client(url, config);

This code is working fine. Please share your code if you are still getting this issue.

Thanks, Shivendra

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/Microsoft/cpprestsdk/issues/199#issuecomment-320788209, or mute the thread https://github.com/notifications/unsubscribe-auth/ACnGcN5EQ2PxFvBAs-mKRYMuIVYbLTRbks5sV4QOgaJpZM4JKVM2 .

xqp commented 7 years ago

Hey Mates :)

the method set_validate_certificate(false) validate the server tls certificate. But if you want to validate with a client certificate you need to call something like this


web::http::client::http_client_config config;
    auto func = [&] (web::http::client::native_handle handle) {
        PCCERT_CONTEXT hContext = /* find your certificate here*/

        WinHttpSetOption(handle, WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
                         (LPVOID) hContext, sizeof(CERT_CONTEXT) );
    };

    config.set_nativehandle_options(func);
    http_client client(url, config);

other possible stuff.. check the supported tls version from your windows 7. This is possible with the the native handle callback from above. Check which tls version is supported by your server. After that you should check which tls version your windows 7 supports.

web::http::client::http_client_config config;
    auto func = [&] (web::http::client::native_handle handle) {
BOOL win32Result{FALSE};
    DWORD secure_protocols{WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1
                         | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2};
    win32Result = ::WinHttpSetOption(handle,
                                     WINHTTP_OPTION_SECURE_PROTOCOLS,
                                     &secure_protocols,
                                     sizeof(secure_protocols));
    if (FALSE == win32Result) {
        std::cout << "Can not set TLS 1.1 or TLS 1.2." << std::endl;
    }
}
shivendra6782 commented 7 years ago

Hi, I developed the same on Windows 7 64 Bit OS. While I am using development rest server which is having Self signed certificate, i need to set validate certificate as false to be working. (config.set_validate_certificates(false);) . But in case if we have signed certificate, then set it to true. And also can you please check with your REST Server API team, what settings they have configured for server because if they have configured, to validate client certificate also then you need send client certificate as mentioned above otherwise server will not allow to communicate e.g. suppose your server is expecting certificate like ..@companydomain.com, then all machine having valid certificate , can communicate with the server(and obviously your app will be using the same while making Secure connection with the server.)

And also we should validate server certificate also for security reasons because how you will make sure you are connected to the authenticated server that is called SSL pinning.

Check your TLS version as well, both side it should be same or higher.

Thanks, Shivendra

sinall commented 6 years ago

@xqp I tried the set_nativehandle_options as you mentioned on Aug 8. I expected to see exception but didn't with 3 cases:

  1. I left the body of func as empty
  2. I even tried to set_validate_certificate to true or false
  3. I used a wrong cert from wrong pem file

I can see the func is stopped when I make a breakpoint. But it seems that the func doesn't have any impact to the client.

Any idea?

Tom883 commented 6 years ago

@xqp, I’ve registered a callback as you suggested using the set_nativehandle_options. Then upon invocation of WinHttpSetOption on the handle that is being passed to the callback , I receive the ERROR_WINHTTP_INCORRECT_HANDLE_TYPE error. Maybe the callback receive a handle to the request and not a handle to the session that WINHTTP_OPTION_SECURE_PROTOCOLS option expects? Is there a way to get the session handle from the request handle? Thanks

chenziliang commented 6 years ago

Look like 2 concrete examples for Win and Linux platforms for how to pass in the cert for http_client are highly on-demand here.

SailingDreams commented 6 years ago

Anyone found a replacement option for WinHttpSetOption() to use in Linux?