4

Sage Pay today ended their exemption for sites to use SSL3 when communicating with their payment / authorisation servers. TLSv1 is now required.

We have a Windows Server 2003 box running IIS6, and two sites written (sadly) in Classic ASP. The box has been patched / registry keys updated to mitigate against POODLE, and various online checkers back this up. The server should be using TLS ONLY.

However, when trying to authorise a Sage Pay transaction using WinHttp.WinHttpRequest.5.1 and a POST, the attempt fails immediately. The only error fed back by WinHttpRequest is "-2147483638 - WinHttp.WinHttpRequest - The data necessary to complete this operation is not yet available."

Internet Explorer on the same server is also unable to access the Sage Pay adminstration interfaces hosted on the same URLs. This, despite SSLv2 and SSLv3 being turned off in Internet Options. Again, TLSv1 should be the only option available to ANYTHING on the box.

It doesn't matter what timeouts or options I put on the WinHttp object - it fails so quickly it's almost like it hasn't even tried.

I have verified that the server in question CAN communicate with Sage Pay's servers by using curl. curl works either without a protocol specified (it uses TLS) or by manually specifying - and won't when SSL2 or 3 is specified - as expected.

If that works, why won't anything else - when every bit of server configuration says it should?

Here is a small sample of code which returns the above quoted WinHttpRequest error:

<%
VSPServer = "https://test.sagepay.com/showpost/showpost.asp"

Set objHTTP = Server.CreateObject("WinHttp.WinHttprequest.5.1")
On Error Resume Next
objHTTP.Open "POST",CStr(VSPServer),False
objHTTP.Send "Hello"

If Err.Number <> 0 Then
    Response.Write "Status: " & objHTTP.Status & "<p>"
    Response.Write Err.Number & " - " & Err.Source & " - " & Err.Description
End If

On Error Goto 0
Set objHTTP = Nothing
%>

If False is changed to True (to run this async) in the objHTTP.Open line, the script returns nothing. This script worked prior to Sage Pay turning things off this afternoon.

MikkyX
  • 303
  • 3
  • 15
  • 1
    Please [show us your code](http://stackoverflow.com/help/mcve). – GoBusto Mar 18 '15 at 16:10
  • This maybe related - [WinHttp TLS connection in classic asp](http://stackoverflow.com/q/29098446/692942) – user692942 Mar 18 '15 at 16:16
  • 1
    Before we can help it would be really helpful to see the code that sends the request to SagePay, otherwise we are just guessing. – user692942 Mar 18 '15 at 16:18
  • 1
    Whoever voted to close this as *"Off Topic"* because *"Questions on **professional server- or networking-related infrastructure administration** are off-topic for Stack Overflow unless they directly involve programming or programming tools. You may be able to get help on [sf]."* your reasoning is flawed this relates directly to programming. – user692942 Mar 18 '15 at 16:20
  • 1
    I've edited my post to add a code sample – MikkyX Mar 18 '15 at 16:25
  • @Lankymart , thanks for the link - I've checked and I see you recommend the option(9) argument - sadly this doesn't help. If I copy his code sample and try it, I get the exact same error as my code above. – MikkyX Mar 18 '15 at 16:28
  • From what I've read the going to be getting the correct value for `objHTTP.option(9) = ?` according to the documentation on [MSDN](https://msdn.microsoft.com/en-us/library/windows/desktop/aa384066(v=vs.85).aspx) - *"Sets an unsigned long integer value that specifies which secure protocols are acceptable. By default only SSL3 and TLS1 are enabled. Can by a combination of one or more of the following values."* So if you are using TLSv1 you should be ok, but are you sure SagePay doesn't use TLSv1.1 or TLSv1.2? – user692942 Mar 18 '15 at 17:09
  • I've spoken to Sage Pay a couple of times this afternoon and they've confirmed TLSv1.0 is sufficient. They're as baffled by this as I am, too. Regards the code fix, objHTTP.Option(9) = 128 (or &H80) should force TLSv1 and turn the others off - but it seems to have no effect. – MikkyX Mar 18 '15 at 17:20
  • The advice in that post looks a bit incomplete because reading in the [MSDN documentation](https://msdn.microsoft.com/en-us/library/windows/desktop/aa384066(v=vs.85).aspx) under **WINHTTP_OPTION_SECURE_PROTOCOLS** it seems to suggest there is six different flags that can be set. – user692942 Mar 18 '15 at 17:20
  • Just tested your code using `wscript.exe` (removing the Classic ASP specific syntax and outputting using `MsgBox()` syntax) and I get a status of `200`. No error, didn't even need the `option(9)`?? I'm running *Windows 7 Professional x64 - Service Pack 1*. – user692942 Mar 18 '15 at 17:29
  • Might be the server config this might help - [How to disable PCT 1.0, SSL 2.0, SSL 3.0, or TLS 1.0 in Internet Information Services](https://support.microsoft.com/en-gb/kb/187498?wa=wsignin1.0). – user692942 Mar 18 '15 at 17:34
  • Thanks for continuing to reply, @Lankymart. The link you've posted there is the instructions for changing the registry keys to disable SSL 2 / 3 etc. - we've done all of this already as it's required to mitigate the POODLE vulnerability. This should've been sufficient to make things work, but something, somewhere has gone wrong. I'll recheck it all again tomorrow. – MikkyX Mar 18 '15 at 20:16
  • I had what sounds like a very similar problem some time ago, although in .NET. Internet Explorer was also unable to access the SSL URL. I solved the problem using IISCrypto (https://www.nartac.com/Products/IISCrypto/) which alters the SSL settings in the registry for common scenarios such as PCI compliance. Might be worth a try. – johna Mar 18 '15 at 22:32
  • Hi @John - thanks for the IISCrypto suggestion. I tried it with Best Practices yesterday and it didn't help - I'll try the other combinations. Maybe Best Practices was going a bit far! – MikkyX Mar 19 '15 at 08:18

2 Answers2

2

It doesn't matter what timeouts or options I put on the WinHttp object - it fails so quickly it's almost like it hasn't even tried.

The only error fed back by WinHttpRequest is "-2147483638 - WinHttp.WinHttpRequest - The data necessary to complete this operation is not yet available."

Sounds like you've made an asynchronous request but did not wait for response.

First, you need to figure it out by calling WaitForResponse.
And Second, have to set which secure protocol(s) can be used for the connection.

Try the following code and let me know if the problem still persists.

Option Explicit

Const   WinHttpRequestOption_SecureProtocols = 9
Const   SecureProtocol_SSL2 = 8, SecureProtocol_SSL3 = 32, _
        SecureProtocol_TLS1 = 128, SecureProtocol_TLS1_1 = 512, _
        SecureProtocol_TLS1_2 = 2048

Dim objHTTP
Set objHTTP = Server.CreateObject("WinHttp.WinHttprequest.5.1")
    objHTTP.Open "GET", "https://test.sagepay.com/showpost/showpost.asp", True
    objHTTP.Option(WinHttpRequestOption_SecureProtocols) = SecureProtocol_TLS1
    objHTTP.Send
    If objHTTP.WaitForResponse(30) Then 'wait up to 30 seconds
        'response is ready
        Response.Write "Status : " & objHTTP.Status & "<br />"
        Response.Write "Response Length : " & LenB(objHTTP.ResponseBody)
    Else
        'Request timed out
        Response.Write "Request timed out"
    End If
Set objHTTP = Nothing
Kul-Tigin
  • 16,728
  • 1
  • 35
  • 64
  • Hi, and thanks for this. Unfortunately it 500 errors instantly, with the error being as follows: ASP ERROR INFORMATION: ASP Code: Error No.: -2146893018 Source Code: Category: WinHttp.WinHttpRequest Error in File: /ssl_test2.asp Line: 14 Column: -1 Desc.: The message received was unexpected or badly formatted. Line 14 being the WaitForResponse line. I should've said in my original post that the code worked perfectly before Sage Pay switched things off - and we have the same script / library working on other servers running more up to date OSes. – MikkyX Mar 19 '15 at 08:16
  • They did say in the original post that they tried switching between `False` and `True` on the `objHTTP.Open()` function it's possible that they just posted the error after running with the async flag set to `True`. Kudos for specifying the constant values for the `WinHttpRequestOption_SecureProtocols`. – user692942 Mar 19 '15 at 09:34
  • I tried this, but received the following error: `Invalid procedure call or argument: 'objHTTP.option'` – kneidels Nov 08 '16 at 23:42
2

I have now managed to resolve this. After changing the nature of my search for the problem I discovered that Win2003 uses a different encryption algorithm to connect to servers, even via TLS. It uses 3DES whereas SagePay expects AES. (Source: SagePay Protocol Violation Error)

This led me to install the hotfix linked from Richard Day's answer (http://hotfixv4.microsoft.com/Windows%20Server%202003/sp3/Fix192447/3790/free/351385_ENU_i386_zip.exe - this is the fix for 32 bit English - the hotfix page is here: https://support.microsoft.com/kb/948963) - and, after a reboot, everything fell into place.

Thank you to everyone who made suggestions. It looks like, in the end, it was a problem at the server level. If that requires that this post be moved (as it's no longer programming related), then please do so.

Community
  • 1
  • 1
MikkyX
  • 303
  • 3
  • 15
  • 1
    It's still directly related, so I think it should stay here. After running a modified version of your script through `wscript.exe` and it returning HTTP status of `200` I knew it had to be the server configuration. Glad it's sorted. – user692942 Mar 19 '15 at 09:27