You can use this as a base. This code uses cryptlib
Code: Select all
EnableExplicit
#debugIn = 1
#debugOut = 2
Global NewList programList.s()
Global NewList progVersions.s()
Global homeDrive.s = "d:"
XIncludeFile "\dev\purebasic\utilities\ssl_client64.pbi"
;****************************************************************************************
; write to the log
;****************************************************************************************
Procedure.i WriteToLog(*logtext)
PrintN("Error!!!")
PrintN(PeekS(*logtext))
EndProcedure
;****************************************************************************************
; write to the debugger
;****************************************************************************************
Procedure.i DebugString(*debugData, returnLength.i, *netSource, debugThis.i, returnValue.i, *sslError)
Protected errorText.s = PeekS(*sslError)
If errorText <> ""
ConsoleColor(12,0)
PrintN(errorText)
EndIf
If debugThis = #debugIn
ConsoleColor(10,0)
Else
ConsoleColor(14,0)
EndIf
PrintN(PeekS(*debugData))
ConsoleColor(15,0)
EndProcedure
;****************************************************************************************
; connect, send the get request, then read data in from the secure server
;****************************************************************************************
Procedure.i getMapData()
Protected logText.s
Protected retValue.i
Protected lenghtTTS.i
Protected *errorReturn
Protected *serverReply
Protected sslSession.i
Protected bytesRecvd.i
Protected textToSend.s
Protected debugThis.i = 1
Protected serverName.s = "maps.googleapis.com"
Protected serverPort.i = 443
Protected portTimeout.i = 100
Protected maxAttempts.i = 50
Protected receiveSize.i = 32767
Protected errorTxSize.i = 2047
Protected lenServerName.i = Len(serverName)
*errorReturn = AllocateMemory(errorTxSize)
*serverReply = AllocateMemory(receiveSize)
; create the ssl session
retValue = CryptCreateSession(@sslSession, #CRYPT_UNUSED, #CRYPT_SESSION_SSL)
If retValue <> #CRYPT_OK
logText = "getMapData() > CryptCreateSession error: " + lookupError(retValue)
WriteToLog(@logText)
EndIf
; add the server name
retValue = CryptSetAttributeString(sslSession, #CRYPT_SESSINFO_SERVER_NAME, @serverName, lenServerName)
If retValue <> #CRYPT_OK
logText = "getMapData() > CryptSetAttributeString error: " + lookupError(retValue)
WriteToLog(@logText)
EndIf
; specify the Port, for SSL https, it's 443
If retValue = #CRYPT_OK
retValue = CryptSetAttribute(sslSession, #CRYPT_SESSINFO_SERVER_PORT, serverPort)
If retValue <> #CRYPT_OK
logText = "getMapData() > CryptSetAttribute error: " + lookupError(retValue)
WriteToLog(@logText)
EndIf
EndIf
; activate the ssl session
If retValue = #CRYPT_OK
retValue = CryptSetAttribute(sslSession, #CRYPT_SESSINFO_ACTIVE, 1)
If retValue <> #CRYPT_OK
logText = "getMapData() > CryptSetAttribute error: " + lookupError(retValue)
WriteToLog(@logText)
EndIf
EndIf
; send the GET string to server
If retValue = #CRYPT_OK
textToSend = "GET /maps/api/geocode/xml?address=13921+US19+N,Clearwater,FL,33764&sensor=false HTTP/1.1" + #CRLF$
textToSend + "Accept: */*" + #CRLF$
textToSend + "Accept-Language: en-us" + #CRLF$
textToSend + "Host: maps.google.com" + #CRLF$
textToSend + "Connection: Keep-Alive" + #CRLF$ + #CRLF$
lenghtTTS = Len(textToSend)
retValue = sslSendData(sslSession, *errorReturn, @textToSend, lenghtTTS, @serverName, debugThis)
If retValue <> #CRYPT_OK
logText = "Send GET Statement > sslSendData ERROR: " + lookupError(retValue)
WriteToLog(@logText)
EndIf
EndIf
; receive response from GET command
If retValue = #CRYPT_OK
retValue = sslRecvData(sslSession, *errorReturn, *serverReply, bytesRecvd, receiveSize, portTimeout, maxAttempts, @serverName, debugThis)
If retValue <> #CRYPT_OK
logText = "Receive GET Statement > sslRecvData ERROR: " + lookupError(retValue)
WriteToLog(@logText)
EndIf
EndIf
; now end the ssl session
If sslSession
CryptDestroySession(sslSession)
EndIf
EndProcedure
Define result.i
OpenConsole()
; Initialize the newtork and the crypt Library
PrintN("About to open crypt library")
result = cryptInitialize()
PrintN("Opened crypt library, about to get the map")
getMapData()
; Close the Library
CryptEnd()
Input()
CloseConsole()
Code: Select all
; ------------------------------------------------------------
; Program name: ssl_client64.pbi
; ------------------------------------------------------------
; **********************************************************************************
; initialization of crypt library variables
; **********************************************************************************
; cutdown version for SSL SMTP, 64 bit version
Declare.l cryptInit()
Declare.l cryptEnd()
Declare.l cryptSetAttribute(hCrypt.l,CryptAttType.l, value.l)
Declare.l cryptSetAttributeString(hCrypt.l, CryptAttType.l, pBuff.l, StrLen.l)
Declare.l cryptCreateSession(pSession.l, cryptUser.l, SessionType.l)
Declare.l cryptDestroySession(session.l)
Declare.l cryptCreateEnvelope(penvelope.l, cryptUser.l, FormatType.l)
Declare.l cryptDestroyEnvelope(envelope.l)
Declare.l cryptPushData(envelope.l, pBuff.l, StrLen.l, pBytesCopied.l)
Declare.l cryptFlushData(envelope.l)
Declare.l cryptPopData(envelope.l, pBuff.l, StrLen.l, pBytesCopied.l)
Declare.s lookupError(errorCode.l)
; /****************************************************************************
; * General Constants *
; ****************************************************************************/
#CRYPTLIB_VERSION = 3330
#CRYPT_MAX_KEYSIZE = 256 ; /* The maximum user key size - 2048 bits */
#CRYPT_MAX_IVSIZE = 32 ; /* The maximum IV size - 256 bits */
#CRYPT_MAX_PKCSIZE = 512 ; The maximum public-key component size - 4096 bits, and maximum component
#CRYPT_MAX_PKCSIZE_ECC = 72 ; size FOR ECCs - 576 bits (TO HANDLE the P521 curve) */
#CRYPT_MAX_HASHSIZE = 32 ; /* The maximum hash size - 256 bits */
#CRYPT_MAX_TEXTSIZE = 64 ; /* The maximum size of a text string (e.g.key owner name) */
#CRYPT_USE_DEFAULT = -100 ; A magic value indicating that the default setting
#CRYPT_UNUSED = -101 ; /* A magic value for unused parameters */
#CRYPT_SESSION_SSL = 03 ; /* SSL/TLS */
#CRYPT_SESSINFO_ACTIVE = 6001 ; /* Whether session is active */
#CRYPT_SESSINFO_SERVER_NAME = 6008 ; /* SERVER NAME */
#CRYPT_SESSINFO_SERVER_PORT = 6009 ; /* SERVER PORT number */
; /****************************************************************************
; * STATUS Codes *
; ****************************************************************************/
; /* Errors in function calls */
#CRYPT_OK = 0 ; /* No error */
#CRYPT_ERROR_PARAM1 = -1 ; /* Bad argument, parameter 1 */
#CRYPT_ERROR_PARAM2 = -2 ; /* Bad argument, parameter 2 */
#CRYPT_ERROR_PARAM3 = -3 ; /* Bad argument, parameter 3 */
#CRYPT_ERROR_PARAM4 = -4 ; /* Bad argument, parameter 4 */
#CRYPT_ERROR_PARAM5 = -5 ; /* Bad argument, parameter 5 */
#CRYPT_ERROR_PARAM6 = -6 ; /* Bad argument, parameter 6 */
#CRYPT_ERROR_PARAM7 = -7 ; /* Bad argument, parameter 7 */
;/* Errors due to insufficient resources */
#CRYPT_ERROR_MEMORY = -10 ; /* Out of memory */
#CRYPT_ERROR_NOTINITED = -11 ; /* Data has not been initialised */
#CRYPT_ERROR_INITED = -12 ; /* Data has already been init;d */
#CRYPT_ERROR_NOSECURE = -13 ; /* Opn.not avail.at requested sec.level */
#CRYPT_ERROR_RANDOM = -14 ; /* No reliable random data available */
#CRYPT_ERROR_FAILED = -15 ; /* Operation failed */
#CRYPT_ERROR_INTERNAL = -16 ; /* Internal consistency check failed */
;/* Security violations */
#CRYPT_ERROR_NOTAVAIL = -20 ; /* This type of opn.not available */
#CRYPT_ERROR_PERMISSION = -21 ; /* No permiss.TO perform this operation */
#CRYPT_ERROR_WRONGKEY = -22 ; /* Incorrect key used to decrypt data */
#CRYPT_ERROR_INCOMPLETE = -23 ; /* Operation incomplete/still IN progress */
#CRYPT_ERROR_COMPLETE = -24 ; /* Operation complete/can;t Continue */
#CRYPT_ERROR_TIMEOUT = -25 ; /* Operation timed out before completion */
#CRYPT_ERROR_INVALID = -26 ; /* Invalid/inconsistent information */
#CRYPT_ERROR_SIGNALLED = -27 ; /* Resource destroyed by extnl.event */
;/* High-level function errors */
#CRYPT_ERROR_OVERFLOW = -30 ; /* Resources/space exhausted */
#CRYPT_ERROR_UNDERFLOW = -31 ; /* Not enough data available */
#CRYPT_ERROR_BADDATA = -32 ; /* Bad/unrecognised data format */
#CRYPT_ERROR_SIGNATURE = -33 ; /* Signature/integrity check failed */
;/* Data access function errors */
#CRYPT_ERROR_OPEN = -40 ; /* Cannot OPEN object */
#CRYPT_ERROR_READ = -41 ; /* Cannot READ item from object */
#CRYPT_ERROR_WRITE = -42 ; /* Cannot WRITE item to object */
#CRYPT_ERROR_NOTFOUND = -43 ; /* Requested item not found in object */
#CRYPT_ERROR_DUPLICATE = -44 ; /* Item already present in object */
;/* Data enveloping errors */
#CRYPT_ENVELOPE_RESOURCE = -50 ; /* Need resource to proceed */
;/* User defined errors here */
#CRYPT_HTTP_ERROR = -498 ; /* Error with HTTP protocol */
#CRYPT_SMTP_ERROR = -499 ; /* Error with SMTP protocol */
; /****************************************************************************
; * initialization *
; ****************************************************************************/
Procedure.l cryptInitialize()
; declare the variables needed
Global cryptLib.l = OpenLibrary(#PB_Any, "\Utilities\cryptlib64.dll")
Global *cryptInit = GetFunction(cryptLib, "cryptInit")
Global *cryptEnd = GetFunction(cryptLib, "cryptEnd")
Global *cryptSetAttribute = GetFunction(cryptLib, "cryptSetAttribute")
Global *cryptSetAttributeString = GetFunction(cryptLib, "cryptSetAttributeString")
Global *cryptCreateSession = GetFunction(cryptLib, "cryptCreateSession")
Global *cryptDestroySession = GetFunction(cryptLib, "cryptDestroySession")
Global *cryptCreateEnvelope = GetFunction(cryptLib, "cryptCreateEnvelope")
Global *cryptDestroyEnvelope = GetFunction(cryptLib, "cryptDestroyEnvelope")
Global *cryptPushData = GetFunction(cryptLib, "cryptPushData")
Global *cryptFlushData = GetFunction(cryptLib, "cryptFlushData")
Global *cryptPopData = GetFunction(cryptLib, "cryptPopData")
; Initialize the crypt Library
Protected initValue.l = CryptInit()
Protected initResult.l
If initValue = #CRYPT_OK
initResult = #True
Else
initResult = #False
EndIf
ProcedureReturn initResult
EndProcedure
;****************************************************************************************
; receive data from a server encrypted by ssl
;****************************************************************************************
Procedure.l sslRecvData(secureSession.l, *sslError, *returnData, *returnLength, bufferSize.l, socketTimeout.l, maxReadTrys.l, *netSource, debugThis.l)
Protected returnValue.l = 0
Protected attemptCount.l = 0
; initialize the return data
PokeI(*returnLength, 0)
FillMemory(*returnData, bufferSize)
; get incoming data from server, wait as needed
Repeat
Delay(socketTimeout)
attemptCount = attemptCount + 1
If attemptCount > maxReadTrys; if still nothing received, just get out
Break
EndIf
returnValue = CryptPopData(secureSession, *returnData, bufferSize, *returnLength)
If returnValue = #CRYPT_OK
If PeekI(*returnLength) > 0
Break
EndIf
Else
PokeS(*sslError, "CryptPopData ERROR: " + lookupError(returnValue))
Break
EndIf
ForEver
; send the data we have read to the debugger listing, if needed
If debugThis
DebugString(*returnData, PeekI(*returnLength), *netSource, #debugIn, returnValue, *sslError)
EndIf
ProcedureReturn returnValue
EndProcedure
;****************************************************************************************
; send data to a server encrypted by ssl
;****************************************************************************************
Procedure.l sslSendData(secureSession.l, *sslError, *sendText, lenSendText, *netSource, debugThis.l)
Protected returnValue.l = 0
Protected bytesSent.l = 0
; copy data into an encrypted envelope
returnValue = CryptPushData(secureSession, *sendText, lenSendText, @bytesSent)
If returnValue <> #CRYPT_OK Or lenSendText <> bytesSent
PokeS(*sslError, "CryptPushData ERROR " + lookupError(returnValue) + ", lenSend = " + Str(lenSendText) + ", bytesSent = " + Str(bytesSent))
EndIf
; send encrypted data to server
If returnValue = #CRYPT_OK
returnValue = CryptFlushData(secureSession)
If returnValue <> #CRYPT_OK
PokeS(*sslError, "CryptFlushData ERROR " + lookupError(returnValue))
EndIf
EndIf
; send the result of the send to the debugger listing, if needed
If debugThis
DebugString(*sendText, bytesSent, *netSource, #debugOut, returnValue, *sslError)
EndIf
ProcedureReturn returnValue
EndProcedure
; /****************************************************************************
; * General Functions *
; ****************************************************************************/
Procedure.l cryptInit()
ProcedureReturn CallFunctionFast(*cryptInit)
EndProcedure
Procedure.l cryptEnd()
ProcedureReturn CallFunctionFast(*cryptEnd)
EndProcedure
Procedure.l cryptSetAttribute(hCrypt.l,CryptAttType.l, value.l)
ProcedureReturn CallFunctionFast(*cryptSetAttribute, hCrypt.l, CryptAttType.l, value.l)
EndProcedure
Procedure.l cryptSetAttributeString(hCrypt.l, CryptAttType.l, pBuff.l, StrLen.l)
ProcedureReturn CallFunctionFast(*cryptSetAttributeString, hCrypt.l, CryptAttType.l, pBuff.l, StrLen.l)
EndProcedure
; /****************************************************************************
; * Envelope & Session Functions *
; ****************************************************************************/
Procedure.l cryptCreateSession(pSession.l, cryptUser.l, SessionType.l)
ProcedureReturn CallFunctionFast(*cryptCreateSession, pSession.l, cryptUser.l, SessionType.l)
EndProcedure
Procedure.l cryptDestroySession(session.l)
ProcedureReturn CallFunctionFast(*cryptDestroySession, session.l)
EndProcedure
Procedure.l cryptCreateEnvelope(penvelope.l, cryptUser.l, FormatType.l)
ProcedureReturn CallFunctionFast(*cryptCreateEnvelope, penvelope.l, cryptUser.l, FormatType.l)
EndProcedure
Procedure.l cryptDestroyEnvelope(envelope.l)
ProcedureReturn CallFunctionFast(*cryptDestroyEnvelope, envelope.l)
EndProcedure
Procedure.l cryptPushData(envelope.l, pBuff.l, StrLen.l, pBytesCopied.l)
ProcedureReturn CallFunctionFast(*cryptPushData, envelope.l, pBuff.l, StrLen.l, pBytesCopied.l)
EndProcedure
Procedure.l cryptFlushData(envelope.l)
ProcedureReturn CallFunctionFast(*cryptFlushData, envelope.l)
EndProcedure
Procedure.l cryptPopData(envelope.l, pBuff.l, StrLen.l, pBytesCopied.l)
ProcedureReturn CallFunctionFast(*cryptPopData, envelope.l, pBuff.l, StrLen.l, pBytesCopied.l)
EndProcedure
; /***************************************************************************** *
; * User Interface Functions *
; ****************************************************************************/
Procedure.s lookupError(errorCode.l)
Select errorCode
Case #CRYPT_OK
ProcedureReturn ""
Case #CRYPT_ERROR_PARAM1
ProcedureReturn "Bad argument - parameter 1"
Case #CRYPT_ERROR_PARAM2
ProcedureReturn "Bad argument - parameter 2"
Case #CRYPT_ERROR_PARAM3
ProcedureReturn "Bad argument - parameter 3"
Case #CRYPT_ERROR_PARAM4
ProcedureReturn "Bad argument - parameter 4"
Case #CRYPT_ERROR_PARAM5
ProcedureReturn "Bad argument - parameter 5"
Case #CRYPT_ERROR_PARAM6
ProcedureReturn "Bad argument - parameter 6"
Case #CRYPT_ERROR_PARAM7
ProcedureReturn "Bad argument - parameter 7"
Case #CRYPT_ERROR_MEMORY
ProcedureReturn "Out of memory"
Case #CRYPT_ERROR_NOTINITED
ProcedureReturn "Data has not been initialized"
Case #CRYPT_ERROR_INITED
ProcedureReturn "Data has already been initialized"
Case #CRYPT_ERROR_NOSECURE
ProcedureReturn "Operation not available at requested security level"
Case #CRYPT_ERROR_RANDOM
ProcedureReturn "No reliable random data available"
Case #CRYPT_ERROR_FAILED
ProcedureReturn "Operation failed"
Case #CRYPT_ERROR_INTERNAL
ProcedureReturn "Internal consistency check failed"
Case #CRYPT_ERROR_NOTAVAIL
ProcedureReturn "This type of operation not available"
Case #CRYPT_ERROR_PERMISSION
ProcedureReturn "No permission to perform this operation"
Case #CRYPT_ERROR_WRONGKEY
ProcedureReturn "Incorrect key used to decrypt data"
Case #CRYPT_ERROR_INCOMPLETE
ProcedureReturn "Operation incomplete/still in progress"
Case #CRYPT_ERROR_COMPLETE
ProcedureReturn "Operation complete/can't continue"
Case #CRYPT_ERROR_TIMEOUT
ProcedureReturn "Operation timed out before completion"
Case #CRYPT_ERROR_INVALID
ProcedureReturn "Invalid/inconsistent information"
Case #CRYPT_ERROR_SIGNALLED
ProcedureReturn "Resource destroyed by external event"
Case #CRYPT_ERROR_OVERFLOW
ProcedureReturn "Resources/space exhausted"
Case #CRYPT_ERROR_UNDERFLOW
ProcedureReturn "Not enough data available"
Case #CRYPT_ERROR_BADDATA
ProcedureReturn "Bad/unrecognised data format"
Case #CRYPT_ERROR_SIGNATURE
ProcedureReturn "Signature/integrity check failed"
Case #CRYPT_ERROR_OPEN
ProcedureReturn "Cannot open object"
Case #CRYPT_ERROR_READ
ProcedureReturn "Cannot read item from object"
Case #CRYPT_ERROR_WRITE
ProcedureReturn "Cannot write item to object"
Case #CRYPT_ERROR_NOTFOUND
ProcedureReturn "Requested item not found in object"
Case #CRYPT_ERROR_DUPLICATE
ProcedureReturn "Item already present in object"
Case #CRYPT_ENVELOPE_RESOURCE
ProcedureReturn "Need resource to proceed"
Default
ProcedureReturn "Unknown error code: " + Str(errorCode)
EndSelect
EndProcedure