Results 1 to 14 of 14

Thread: SSPI/Schannel client for SSL/TLS channels in VB6

  1. #1

    Thread Starter
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    SSPI/Schannel client for SSL/TLS channels in VB6

    https://github.com/wqweto/VbAsyncSocket

    FYI, these are generic/thin WinSock API wrappers for non-blocking sockets (that optionally can even block if desired), very similar to CAsyncSocket/CSocket classes from olden MFC C++ library.

    The repo also includes a cTlsClient class (~850 LOC) under `contrib` folder, which implements SSL/TLS secure sockets using OS provided SSPI/Schannel API for the heavy lifting i.e. w/o any external dependencies. Couldn't find similar simple and reliable implementation in the CodeBank, between all the noise and false positives couttsj's submissions seem to generate on the search topic.

    Here is a sample code for STARTTLS over SMTP to smtp.gmail.com port 587

    vb Code:
    1. With New cTlsClient
    2.     .Connect "smtp.gmail.com", 587
    3.     Debug.Print .ReadText();
    4.     .WriteText "HELO 127.0.0.1" & vbCrLf
    5.     Debug.Print .ReadText();
    6.     .WriteText "STARTTLS" & vbCrLf
    7.     Debug.Print .ReadText();
    8.     .StartTls "smtp.gmail.com"
    9.     Debug.Print "TLS handshake complete: " & .TlsHostAddress
    10.     .WriteText "QUIT" & vbCrLf
    11.     Debug.Print .ReadText();
    12. End With
    . . . which produces something like this in Immediate window:

    Code:
    220 smtp.gmail.com ESMTP l8sm10315047wmf.39 - gsmtp
    250 smtp.gmail.com at your service
    220 2.0.0 Ready to start TLS
    TLS handshake complete: smtp.gmail.com
    221 2.0.0 closing connection l8sm10315047wmf.39 - gsmtp
    Basicly the sample starts with plain-text communication to the SMTP server which it later upgrades to a TLS secured channel over the same socket, just before sending the final `QUIT` command.

    Accessing https servers or any other "SMTP/FTP/Whatever over SSL" servers with instances of this class is even easier as `Connect` method has a `UseTls` parameter for the sole purpose of starting TLS channel automagically immediately after connection is established.

    Any suggestions and contributions are always welcome, here or at github!

    cheers,
    </wqw>

  2. #2
    New Member
    Join Date
    Jan 2019
    Posts
    4

    Re: SSPI/Schannel client for SSL/TLS channels in VB6

    Thank you very much for sharing!
    I don't speak English, I have to use Google Translate.
    Due to the Chinese network blockade. Unable to access some websites, only through proxy server.
    I am using your source program.
    How to connect to the https page via the socks5 proxy

    Code:
    '127.0.0.1:1080 is the SOCKS5 proxy server
    Set oTlsClient = pvInitHttpRequest("https://www.google.com/", "127.0.0.1", 1080)
    Code:
    Private Function pvInitHttpRequest(sUrl As String, Optional s5ip$, Optional s5port&) As cTlsClient
    'Omit part of the code.....
        oRetVal.SetTimeouts 0, 2500, 2500, 2500 'Set timeout parameters
        If s5ip$ <> "" And s5port& <> 0 Then   'First connect to the SOCKS5 proxy server
            If Not oRetVal.Connect(s5ip$, s5port&, False) Then GoTo QH
            Debug.Print Format$(TimerEx, "0.000"), "Start connecting to the proxy server " & s5ip$ & ":" & s5port&
            If Not oRetVal.WriteArray(Socks5_Con1) Then GoTo QH
            Debug.Print Format$(TimerEx, "0.000"), "First sent to the proxy server"
            Dim bytData() As Byte
            If Not oRetVal.ReadArray(bytData) Then GoTo QH
            Debug.Print Format$(TimerEx, "0.000"), "Receive the data of the proxy server for the first time"
            If bytData(1) = 255 Then
                Debug.Print Format$(TimerEx, "0.000"), "Connection proxy failed!"
                GoTo QH
            ElseIf bytData(0) = 5 And bytData(1) = 0 Then 'If the agent replies with 05 00 for no authentication, the connection is successful.
                Debug.Print Format$(TimerEx, "0.000"), "The first connection agent was successful! No verification"
                Dim iSiT_host As Boolean
                iSiT_host = Return_IP_Type(sHost)
                If Not oRetVal.WriteText(Socks5_Con2(sHost, lPort, iSiT_host)) Then GoTo QH  'The second step is to verify the connection request
                Debug.Print Format$(TimerEx, "0.000"), "Second time sent to the proxy server"
            End If
            If Not oRetVal.ReadArray(bytData) Then GoTo QH
            If bytData(1) = 0 Then 'The second reply from the proxy server
                Debug.Print Format$(TimerEx, "0.000"), "Connect to through a proxy server" & sHost & lPort & "success."  'In the last step without verification, the agent replies with the second byte being 00 and the rest being a failure.
                'GoTo QH   'Connect OK to start GET or HEAD http request
            Else
                Debug.Print Format$(TimerEx, "0.000"), "Failed to connect to the target server through a proxy!"
                GoTo QH
            End If
        Else
            If Not oRetVal.Connect(sHost, lPort) Then GoTo QH   'Directly connect to the target host when there is no proxy server
            Debug.Print Format$(TimerEx, "0.000"), "Connected to " & sHost & ":" & lPort
        End If
        
        If LCase$(sProto) = "https" Then
            If Not oRetVal.StartTls(sHost) Then GoTo QH  'If it is connected through a proxy "www.google.com:443",How to conduct TLS handshake?
            Debug.Print Format$(TimerEx, "0.000"), "TLS handshake complete"
        End If
        If Not oRetVal.WriteText("GET " & sPath & " HTTP/1.0" & vbCrLf & _
                "Host: " & sHost & vbCrLf & _
                "Connection: close" & vbCrLf & vbCrLf) Then
            GoTo QH
        End If
        Debug.Print Format$(TimerEx, "0.000"), "Request sent"
        Set pvInitHttpRequest = oRetVal
    QH:
    End Function
    oRetVal.StartTls(sHost) =false
    After successfully connecting to the target server through the proxy, the handshake always returns false.
    Now that something went wrong, what should I do?

  3. #3

    Thread Starter
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: SSPI/Schannel client for SSL/TLS channels in VB6

    I just implemented SOCKS5 support for https tunneling in the test project and handshake is working ok here.

    I have no idea how China's Great Firewall is working (probably whole stateful inspection) but it would be insanely simple to circumvent it w/ a simple SOCKS5 proxy, don't you think? Besides, hosting the proxy on localhost tunnels nothing outside The Firewall.

    I'm starting to wonder if the https handshake worked through your connection *without* proxy in first place. If so, you probably messed up SOCKS5 protocol implementation some place -- half of the code is missing in your post, so can't easily tell what went wrong.

    Anyway, SOCKS5 proxy is now impl ok in the Basic test I linked above.

    cheers,
    </wqw>

  4. #4
    New Member
    Join Date
    Jan 2019
    Posts
    4

    Re: SSPI/Schannel client for SSL/TLS channels in VB6

    Thank you very much, with your example you can connect via socks5. And my previous aspects are not good. I have been unable to find the problem, maybe there is a problem here, ignore it. Just use your source program
    oRetVal.WriteText Chr(5) & Chr(1) & Chr(0) & Chr(3) & Chr(Len(Dest_Address)) & _
    Dest_Address & Chr(Int(DestPort / 256)) & Chr(DestPort Mod 256)
    A little,lPort = Val(.Item(2)) Changed to lPort = Val(Mid(.Item(2), 2)) better
    Next, I am going to use the http proxy to get the https page.

  5. #5

    Thread Starter
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: SSPI/Schannel client for SSL/TLS channels in VB6

    Fixed and thank you for the bug report!

    While on fixing url parsing I used the opportunity to add user/pass authentication against the SOCKS5 proxy too.

    cheers,
    </wqw>

  6. #6
    New Member
    Join Date
    Jan 2019
    Posts
    4

    Re: SSPI/Schannel client for SSL/TLS channels in VB6

    It is not a mistake to parse this with url. It's just that the operating environment is different. Like here,
    I must change "Connection: close" change into "Connection: Keep-Alive"
    Code:
    If Mid$(sHeaders, 10, 3) = "302" Then
    change into
    Code:
    If Mid$(sHeaders, 10, 2) = "30" Then
    Code:
    oRetVal.WriteArray pvToByteArray(5, 1, 0, 3) '--- 5 = version, 1 = TCP stream conn, 0 = reserved, 3 = domain name
            baBuffer = oRetVal.Socket.ToTextArray(sHost, ucsScpUtf8)"
            oRetVal.WriteArray pvToByteArray(UBound(baBuffer) + 1)
    change into
    Code:
    addresstype% = 3
            If IsNumeric(Split(StrReverse(sHost), ".")(0)) Then
                addresstype% = 1
            End If '0x01: IPv4 address 0x03: Domain name
            oRetVal.WriteArray pvToByteArray(5, 1, 0, addresstype%) '--- 5 = version, 1 = TCP stream conn, 0 = reserved, 3 = domain name
            If addresstype% = 1 Then
                 ReDim baBuffer(3)
                 baBuffer(0) = Split(sHost, ".")(0)
                 baBuffer(1) = Split(sHost, ".")(1)
                 baBuffer(2) = Split(sHost, ".")(2)
                 baBuffer(3) = Split(sHost, ".")(3)
            Else
                baBuffer = oRetVal.Socket.ToTextArray(sHost, ucsScpUtf8)
                'baBuffer = StrConv(sHost, vbFromUnicode)
                oRetVal.WriteArray pvToByteArray(UBound(baBuffer) + 1)
            End If"

  7. #7

    Thread Starter
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: SSPI/Schannel client for SSL/TLS channels in VB6

    > I must change "Connection: close" change into "Connection: Keep-Alive"

    That would be very different to implement -- parsing the response has to be redone to depend on Content-Length header I think.

    Parsing direct IPs in URL is nice feature to have. I was (secretly) hoping that passing "IP address" to SOCKS5 server as "domain name" would fool the server to "resolve" it to the same IP address :-))

    Recognizing 301 vs 302 redirects seems useful addition too.

    So this proofs the sample code is very bare. It's just a test for the cAsyncSocket class that might be used as a starting point for full protocol implementation if anyone is willing to read the RFCs and test, test, test. . .

    cheers,
    </wqw>

  8. #8

  9. #9
    Junior Member
    Join Date
    Nov 2021
    Posts
    18

    Re: SSPI/Schannel client for SSL/TLS channels in VB6

    Quote Originally Posted by wqweto View Post
    FYI, now VbAsyncSocket repo includes a Winsock control replacement implementation in contrib.

    cheers,
    </wqw>
    Code:
    Public Sub SendData(data As Variant)
        Const FUNC_NAME     As String = "SendData"
        
        On Error GoTo EH
        Select Case VarType(data)
        Case vbString
            m_baSendBuffer = pvSocket.ToTextArray(CStr(data), ucsScpAcp)
        Case vbByte + vbArray
            m_baSendBuffer = data
        Case Else
            Err.Raise vbObjectError, , "Unsupported data type: " & TypeName(data)
        End Select
        If UBound(m_baSendBuffer) >= 0 Then
            m_lSendPos = 0
            m_oSocket_OnSend
        End If
        Exit Sub
    EH:
        PrintError FUNC_NAME
    End Sub
    I'm actually currently still using a variant of CSocket, so maybe it differs from the original Winsock control in this regard, but I think .SendData should not implicitly reset the buffer if there's still unsent data in it. But if the original does it too then well, it's stupid but you have to do it if it's supposed to be a drop-in replacement.

    I'll see how much work it is to switch my project over to this. My CSocket evolved over time to support IPv6 and SSL via openssl, but the idea of getting rid of that dependency is tempting. I'm surprised you mention this would support even NT4.0 with mdTlsThunks - I still see a lot of calls to stuff from advapi32; it's not using any fancy new flags, ciphers and hashes and stuff that NT4 wouldn't understand?

  10. #10

    Thread Starter
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: SSPI/Schannel client for SSL/TLS channels in VB6

    Quote Originally Posted by Zahl View Post
    I'm actually currently still using a variant of CSocket, so maybe it differs from the original Winsock control in this regard, but I think .SendData should not implicitly reset the buffer if there's still unsent data in it. But if the original does it too then well, it's stupid but you have to do it if it's supposed to be a drop-in replacement.
    Yes, you have a point and this looks like a bug. It's not present when using TLS socket because the underlying encrypting routines buffer the whole output so m_baSendBuffer never has outstanding data.

    I'll look to it to append to m_baSendBuffer if m_lSendPos indicates there is some unsent data in it.

    Edit: Fixed in 845f387

    Quote Originally Posted by Zahl View Post
    I'll see how much work it is to switch my project over to this. My CSocket evolved over time to support IPv6 and SSL via openssl, but the idea of getting rid of that dependency is tempting. I'm surprised you mention this would support even NT4.0 with mdTlsThunks - I still see a lot of calls to stuff from advapi32; it's not using any fancy new flags, ciphers and hashes and stuff that NT4 wouldn't understand?
    I test it in couple of VMs with NT4, Win2000, XP, Vista, etc. with "Break on All Errors" set in the IDE. The code has extensive checks on API calls return values so these are raised as VB errors too.

    For the latest WinHttpRequest replacement effort I had time to test it on an XP only for the TLS 1.3 support. More tests with earlier OS versions are to be done for any API calls incompatibility.

    Edit: CSocket is equivalent to cTlsSocket class, not the ctxWinsock control. cTlsSocket class contrary to its name can create both encrypted and plaintext sockets both in async and blocking mode.

    cheers,
    </wqw>

  11. #11
    Registered User
    Join Date
    Feb 2021
    Posts
    2

    Re: SSPI/Schannel client for SSL/TLS channels in VB6

    Hi wqweto,

    Thanks for your great code.
    I am trying to find out any solution which for VB6 with TLS function.
    And I found the topic and your code.

    But I would like to receive mail from Microsoft Exchange POP3 which TLS required.
    Does your project support the POP3 with TLS?

    Cheers,
    Eric Hu

  12. #12

    Thread Starter
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: SSPI/Schannel client for SSL/TLS channels in VB6

    Quote Originally Posted by ieric.hu View Post
    Does your project support the POP3 with TLS?
    It does support TLS encryption for any TCP based protocol but does not explicitly support POP3 protocol (nor SMTP).

    There is a cHttpRequest class (in contrib directory) which implements client-side HTTP so you get HTTP over TLS (so called HTTPS) implemented with it.

    But there is no separate class which implements POP3 over TLS in the repo. You can implement such class using cTlsSocket class for the network transport and you'll get TLS baked in for free.

    cheers,
    </wqw>

  13. #13
    Registered User
    Join Date
    Feb 2021
    Posts
    2

    Re: SSPI/Schannel client for SSL/TLS channels in VB6

    Hi wqweto,

    Thanks for your reply and explanation for it.
    I will try on it

    Thanks!

    Eric Hu

  14. #14
    New Member
    Join Date
    Jan 2022
    Posts
    1

    Re: SSPI/Schannel client for SSL/TLS channels in VB6

    Hi,
    I have a application in VB6. It uses the Socket6 to create connection to a POP3/SMTP server, loads newly arrived mails and sends new created mails. Its now running since several years without problems.
    Now I have to alter the socket to another one enabling SSL/TLS. I am not very familliar with TCP a.s.o. I checked a lot of internet pages and found the VbAsyncSocket. However I am not sure if this product is the right one for my project. My application has to run on XP, Win7, Win10 and Win11.
    Can you help me?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width