POSTing binary data with HTTPS through wininet...
-
I'm having a bit of an issue with sending data through HTTPS via wininet in a C++ test app: I can download any page through HTTP with: InternetOpen( ..., dwFlags ) InternetOpenUrl( ..., "http://...", ..., dwFlags, 0 ) InternetReadFile( ... ) I can download a secured page through HTTPS with the same code with the following changes: InternetOpen( ..., dwFlags | INTERNET_FLAG_SECURE ) InternetOpenUrl( ..., "https://...", ..., dwFlags | INTERNET_FLAG_SECURE, 0 ) InternetReadFile( ... ) At that point my buffer contains the plain/decrypted text, while a packet sniffer only shows encrypted data, telling me that indeed the encryption/decryption happens transparently as far as my program knows. I can upload a binary file through HTTP with: (read file content in some buffer, lpvBuffer) InternetOpen( ..., dwFlags ) dwPort = INTERNET_DEFAULT_HTTP_PORT InternetConnect( ..., lpszServer, dwPort, NULL, NULL, INTERNET_SERVICE_HTTP, dwFlags, ... ) HttpOpenRequest( ..., "POST", lpszPage, ..., dwFlags, 0 ) HttpSendRequest( ..., NULL, // no custom header 0, // so its size isn't needed lpvBuffer, // content of my file dwSizeOfBuffer ) // size of my file/buffer lpvBuffer is the content of my binary file, and dwSizeOfBuffer is its size. I've confirmed that the server correctly receives the file at the other end, and saves it back into a binary file--windiff says they're identical. Great. Everything so far works. Now...my ultimate goal...after all these successful tests...is to upload a binary file through HTTPS... I thought it would be a simple matter of setting the INTERNET_FLAG_SECURE flags again, setting dwPort to INTERNET_DEFAULT_HTTPS_PORT, and going through the same code as shown above (the last snippet)--but it doesn't work. My client appears to send the data and then sits on HttpSendRequest(), waiting for it to return, and eventually times out (ERROR_INTERNET_TIMEOUT). I suspect that the size of the data being actually transmitted over the wire doesn't match the size I specify (dwSizeOfBuffer--the size of my file), since it's now being sent through HTTPS (and not plain HTTP), so--? this is speculation on my part ?--the server is waiting for more data to be sent than I specify in dwSizeOfBuffer, while the client's actually done, so it's also waiting on the server...eventually the client times out. My initial assumption was that as far as my program is concerned, I shouldn't even have to worry about specifying the size of the *encrypted* buffer, and I should only have t
-
I'm having a bit of an issue with sending data through HTTPS via wininet in a C++ test app: I can download any page through HTTP with: InternetOpen( ..., dwFlags ) InternetOpenUrl( ..., "http://...", ..., dwFlags, 0 ) InternetReadFile( ... ) I can download a secured page through HTTPS with the same code with the following changes: InternetOpen( ..., dwFlags | INTERNET_FLAG_SECURE ) InternetOpenUrl( ..., "https://...", ..., dwFlags | INTERNET_FLAG_SECURE, 0 ) InternetReadFile( ... ) At that point my buffer contains the plain/decrypted text, while a packet sniffer only shows encrypted data, telling me that indeed the encryption/decryption happens transparently as far as my program knows. I can upload a binary file through HTTP with: (read file content in some buffer, lpvBuffer) InternetOpen( ..., dwFlags ) dwPort = INTERNET_DEFAULT_HTTP_PORT InternetConnect( ..., lpszServer, dwPort, NULL, NULL, INTERNET_SERVICE_HTTP, dwFlags, ... ) HttpOpenRequest( ..., "POST", lpszPage, ..., dwFlags, 0 ) HttpSendRequest( ..., NULL, // no custom header 0, // so its size isn't needed lpvBuffer, // content of my file dwSizeOfBuffer ) // size of my file/buffer lpvBuffer is the content of my binary file, and dwSizeOfBuffer is its size. I've confirmed that the server correctly receives the file at the other end, and saves it back into a binary file--windiff says they're identical. Great. Everything so far works. Now...my ultimate goal...after all these successful tests...is to upload a binary file through HTTPS... I thought it would be a simple matter of setting the INTERNET_FLAG_SECURE flags again, setting dwPort to INTERNET_DEFAULT_HTTPS_PORT, and going through the same code as shown above (the last snippet)--but it doesn't work. My client appears to send the data and then sits on HttpSendRequest(), waiting for it to return, and eventually times out (ERROR_INTERNET_TIMEOUT). I suspect that the size of the data being actually transmitted over the wire doesn't match the size I specify (dwSizeOfBuffer--the size of my file), since it's now being sent through HTTPS (and not plain HTTP), so--? this is speculation on my part ?--the server is waiting for more data to be sent than I specify in dwSizeOfBuffer, while the client's actually done, so it's also waiting on the server...eventually the client times out. My initial assumption was that as far as my program is concerned, I shouldn't even have to worry about specifying the size of the *encrypted* buffer, and I should only have t
-
You should have a custom header. eg Content-Length: HttpSendRequest will not generate the content-length for you.
> You should have a custom header. eg Content-Length: > > HttpSendRequest will not generate the content-length for you. Are you sure about this? I'm not setting a content-length header, and in HTTP mode, my packet sniffer (Ethereal) shows that a Content-Length header has indeed been generated, with the length I specified in HttpSendRequest()'s dwOptionalLength parameter. The file gets there and a binary comparison shows that it's identical to the one I sent. I just need to do the same with HTTPS. I'm not sure why the header would be required in this case but not the former. Regardless, I tried to do it explicitely with HttpAddRequestHeaders(), and got the exact same results... -- modified at 8:44 Thursday 23rd March, 2006
-
> You should have a custom header. eg Content-Length: > > HttpSendRequest will not generate the content-length for you. Are you sure about this? I'm not setting a content-length header, and in HTTP mode, my packet sniffer (Ethereal) shows that a Content-Length header has indeed been generated, with the length I specified in HttpSendRequest()'s dwOptionalLength parameter. The file gets there and a binary comparison shows that it's identical to the one I sent. I just need to do the same with HTTPS. I'm not sure why the header would be required in this case but not the former. Regardless, I tried to do it explicitely with HttpAddRequestHeaders(), and got the exact same results... -- modified at 8:44 Thursday 23rd March, 2006
"MF", I hate to answer my own post, but I got it to work. Turns out it's got nothing to do with Content-Length headers. I was specifying the IP address of my server instead of its domain name. Since the certificate, apparently, is considered by the client to be valid only if it *exactly* matches the domain name (www.whatever.com), *something* just sat there until my client timed out. If you do the same with IE, it warns you that the name doesn't match, but asks you whether you want to continue anyway. If you specify the exact name matching what the certificate was issued for, IE doesn't give you the warning--that's what clued me in. I now consider myself slightly more educated. :-) Thanks for your assistance, even though it didn't turn out to be the root cause of the problem (I *still* don't specify any length besides the size of the Optional parameter, and it works fine)...