64 bit SSL https
Posted: Sat Dec 29, 2012 5:27 am
				
				This is a continuation of the secure sockets layer code. The following is an example of 64 bit windows code to read an http ssl (https) web page. It uses the same include file as my secure email example from earlier in this forum. The code reads an xml page from Google Maps, but can be adapted to most whatever you need.
http_ssl64.pb
			http_ssl64.pb
Code: Select all
EnableExplicit
XIncludeFile "ssl_mail64.pbi"
#SMTP_RESPONSE_TIMEOUT = 5000 ; m/s
;****************************************************************************************
; receive data from the server encrypted by ssl
;****************************************************************************************
Procedure.i sslRecvData(secureSession.i, *sslError, *returnData, *lenRtnData, buffSize.i)
    Protected retValue.i
    Protected totReturned = 0
    Protected totalMS.i   = 0
; get server response, wait as needed
    Repeat
        Delay(100)
        totalMS = totalMS + 100
        If totalMS > #SMTP_RESPONSE_TIMEOUT
            Break
        EndIf
        retValue = CryptPopData(secureSession, *returnData, buffSize, @totReturned)
        If retValue <> #CRYPT_OK
            PokeS(*sslError, "CryptPopData ERROR: " + lookupError(retValue))
            ProcedureReturn -999
        Else
            If totReturned > 0
                PokeI(*lenRtnData, totReturned)
                Break
            EndIf
        EndIf
    ForEver
    PrintN("Recd:")
    If totReturned > 0
        ConsoleColor(10,0)
        PrintN(PeekS(*returnData, totReturned))
        ConsoleColor(15,0)
    EndIf
    ProcedureReturn retValue
EndProcedure
;****************************************************************************************
; send data to the server encrypted by ssl
;****************************************************************************************
Procedure.i sslSendData(secureSession.i, *sslError, *sendText, lenSendText)
    Protected retValue.i
    Protected bytesSent.i
; used to copy data into an encrypted envelope
    retValue = CryptPushData(secureSession, *sendText, lenSendText, @bytesSent)
    If retValue <> #CRYPT_OK Or lenSendText <> bytesSent
        PokeS(*sslError, "CryptPushData ERROR " + lookupError(retValue) + ", lenSend = " + Str(lenSendText) + ", bytesSent = " + Str(bytesSent))
        ProcedureReturn -998
    EndIf
; send data to server
    retValue = CryptFlushData(secureSession); used to send data to remote machine
    If retValue <> #CRYPT_OK
        PokeS(*sslError, "CryptFlushData ERROR " + lookupError(retValue))
        ProcedureReturn -997
    EndIf
    PrintN("Sent:")
    ConsoleColor(14,0)
    PrintN(PeekS(*sendText, lenSendText))
    ConsoleColor(15,0)
    ProcedureReturn retValue
EndProcedure
;****************************************************************************************
; connect, send the get request, then read data in from the secure server
;****************************************************************************************
Procedure.i getSecurePage(*serverName, lenServerName.i, serverPort.i, *getString, lengthGS, *rtnString, replySize, *rtnError)
    Protected retValue.i
    Protected sslSession.i
    Protected bytesRecvd.i
; create the ssl session
    retValue = CryptCreateSession(@sslSession, #CRYPT_UNUSED, #CRYPT_SESSION_SSL)
    If retValue <> #CRYPT_OK
        PokeS(*rtnError, lookupError(retValue))
        ProcedureReturn retValue
    EndIf
; add the server name
    retValue = CryptSetAttributeString(sslSession, #CRYPT_SESSINFO_SERVER_NAME, *serverName, lenServerName)
    If retValue <> #CRYPT_OK
        PokeS(*rtnError, lookupError(retValue))
        ProcedureReturn retValue
    EndIf
; specify the Port, for https SSL, it's 443
    retValue = CryptSetAttribute(sslSession, #CRYPT_SESSINFO_SERVER_PORT, serverPort)
    If retValue <> #CRYPT_OK
        PokeS(*rtnError, lookupError(retValue))
        ProcedureReturn retValue
    EndIf
; activate the ssl session
    retValue = CryptSetAttribute(sslSession, #CRYPT_SESSINFO_ACTIVE, 1)
    If retValue <> #CRYPT_OK
        PokeS(*rtnError, lookupError(retValue))
        ProcedureReturn retValue
    EndIf
; send the GET string to server
    retValue   = sslSendData(sslSession, *rtnError, *getString, lengthGS)
    If retValue <> #CRYPT_OK
        PokeS(*rtnError, "sslSendData ERROR: " + lookupError(retValue))
        ProcedureReturn retValue
    EndIf
; receive response from GET command
    retValue    = sslRecvData(sslSession, *rtnError, *rtnString, @bytesRecvd, replySize)
    If retValue <> #CRYPT_OK
        PokeS(*rtnError, "sslRecvData ERROR: " + lookupError(retValue))
        ProcedureReturn retValue
    EndIf
; now end the ssl session
    If sslSession
        CryptDestroySession(sslSession)
    EndIf
    ProcedureReturn 0
EndProcedure
Define retValue.i
Define lengthGS.i
Define initValue.i
Define getString.s
Define errReturn.s     = Space(255)
Define replySize.i     = 32767
Define rtnString.s     = Space(replySize)
Define serverName.s    = "maps.googleapis.com"
Define serverPort.i    = 443
Define lenServerName.i = Len(serverName)
getString = "GET /maps/api/geocode/xml?address=13921+US19+N,Clearwater,FL,33764&sensor=false HTTP/1.1" + #CRLF$
getString + "Accept: */*" + #CRLF$
getString + "Accept-Language: en-us" + #CRLF$
getString + "Host: maps.google.com" + #CRLF$
getString + "Connection: Keep-Alive" + #CRLF$ + #CRLF$
lengthGS  = Len(getString)
OpenConsole()
ConsoleColor(15,0)
; Initialize the crypt Library
initValue = CryptInit()
If initValue <> #CRYPT_OK
    errReturn = lookupError(initValue)
    PrintN(errReturn)
EndIf
retValue = getSecurePage(@serverName, lenServerName, serverPort, @getString, lengthGS, @rtnString, replySize, @errReturn)
If retValue <> #CRYPT_OK
    PrintN(errReturn)
Else
    PrintN("connection successful!")
EndIf
CryptEnd() ; Close the Library
Input()
CloseConsole()
; IDE Options = PureBasic 4.61 (Windows - x64)
; ExecutableFormat = Console
; CursorPosition = 81
; FirstLine = 54
; Folding = -
; Executable = http_ssl64.exe
; CompileSourceDirectory
; Compiler = PureBasic 4.61 (Windows - x64)