|
I need a C++ program for SSL client-server handshake, I just came in to C++ and know it at basic level, anybody can send me such codes (for client and server) so I can study more on this specific application. Thanks!!!
tonynguyen
|
|
|
|
|
Hello,
ich have a question about the "SSL Client/Server library and Simple Client/Server" sample app.
I tried to get it work with a private key on the server side and a public key on the client side.
But it didn't work. It only works with the private key on the client side.
This ist not the recommend way for me. I thought (of cause i'm wrong) the communication between
client and server ist asymetric to handle out a symetric key to transfer the data.
Am i wrong with this assumption?
thanks
Stefan
|
|
|
|
|
How to resolve message: Connection failed: Couse: No connection could be made because the target machine actively refused it.
Do I have to add something to SSLServer class or what?
Help me!
Thank you in advance
|
|
|
|
|
Hi:
Thanks for this nice piece of code.
With a few changes, I am trying to use the client as a Windows Service. But the handshake process fails in such a scenario. I am getting SSL_ERROR_SYSCALL while doing SSL_Connect. I think the problem is that the C# callback function (Send) is not getting called when I make it a windows service. Any ideas?
|
|
|
|
|
While implementing SSL, I am getting one exception
Exception: A call to SSPI failed, see inner exception.
Inner exception: The Local Security Authority cannot be contacted
Authentication failed - closing the connection.
The following steps i have done:
1. I had created a Test Certificate using MakeCert.exe (Tool for generating Certificate).
2. After that i had imported that certificate to "My" certificate store.
3. Now i had written Server and Client programs for communicating using Test Certificate.
While Authenticating between client and server the following exception occurred at the server end.
Exception: A call to SSPI failed, see inner exception.
Inner exception: The Local Security Authority cannot be contacted
Authentication failed - closing the connection.
Can any one help for this exception. I am doing desktop client and server which are written in c#.
Ravi Sankar.
ravi_yadavalli@yahoo.co.in
ravi sankar
|
|
|
|
|
Hi Leon
I tried downloading and using many versions of openssl packages
and installed them according to instruction given in your nice article , but after the last command entry in visual studio prompt
it runs and finally gives error messages and installation failuer
due to some ( about 7 ) missing Header files in the packages of openssl , then I tried borrowing those files from Mingo directory
( Mingo is Installed already) ,still failed, and this means that
the folder OUT32 is empty , I did the rest , but could not define or could not solve the OSSL dll which is the heart of the application
Why this is happening ?
Is it due to Openssl packages free downloading source ...and are Incomplete ? Or what softwares needed to be installed .. and I may not have Installed yet ?
Or even I used ( win32-openssl dierct Installer )and Installed
the opensslpackage and did not work again , is that package also
Incomplete as it seems to me or what ?
Please any help , answers which leads as to solve this puzzle .
Thanks for leon
Thanks for any member who contribute to answer the above items.
mohamad
|
|
|
|
|
Most of the SChannel references that you mentioned at the end of the article are not working especially MSDN ones, pls help. I want to learn SChannel and TLS via SSPI.
Please tell any books if read...
Thanks and Regards,
Anand.
|
|
|
|
|
I use it for EAP-TLS. But it must to resume the session.
How to resume TLS session?
|
|
|
|
|
Guys ,
Help , I am recieving this error message failed to acquire credentials .
I have :
installed certificate , register them , in server / client side
i am running the exe with same user account that been used to install the certificate
i am using thawte certificate
|
|
|
|
|
I am trying to get a test certificate pair from the MS test CA server mentioned in this article, but when I click on the link it asks me for a username and password. Where am I supposed to get these credentials from? What I'm talking about is this: "Microsoft's free test Certificate Authority Server located at: http://131.107.152.153/"
Anyone know how to login to that?
|
|
|
|
|
Hello everybody
I download common.zip and it works fine with me but i'm new to ssl so can u please provide me by the algorithm this application is using for encryption.
i knew its aschro but the algorithm used is not clear so if u please can help me with this subject mentioning to me the variable that intialize such algorithm
-- modified at 3:53 Tuesday 6th March, 2007
pleassssssssssssssssssssssssssssssssssssssssssssssssssssssssse help
emma
|
|
|
|
|
I have been able to compile openssl successfully and also compiled the sample openssl code. When I try to run the server part of the code from VS.Net 2003, I get the error:
"File or assembly name SSL, or one of its dependencies, was not found."
it fails at the very first line ie:
SSLServer server = new SSLServer();
Not able to make much sense out of this, since I have been able to compile all the 3 projects successfully and I can see a SSL.dll file in the corresponding debug directory of the server folder.
Any ideas?
vemul
|
|
|
|
|
I think it is refersd to as SSL dll missing.
I found it given in a folder named as SSL too ,if you unzip
the zip file common.zip you will find out that it has been prepared
in C++ files .
but still it is not working since while building the C# application for this SSL Tunnel program it asks for that SSL.dll file and the
program can not find it as it is .
I think we have to create a window like dll file from that given code
and register the dll by : 1- copying the dll into system32 folder and 2- run the command regsrv "SSL.dll" at the comand prompt
then to try to build the project again .
I hope that the idea works .
But how to create that dll file from that C++ SLL dll genrated by
the wizard .. this remains to be done.
any idea about that .. or the dll is where to be down loaded ?
I hope I helped and both finding the solution .
|
|
|
|
|
I have the same issue, and it can not be resolved when I copied the SSL.dll to the system32 folder, and use regsrv32 to register this dll.
I'm using VS2010 for development. The SSL project, SSLServer and SSLWebClient can be compiled successfully, but when I attempt to run SSLServer, the exception "{"Could not load file or assembly 'SSL.dll' or one of its dependencies. The specified module could not be found.":"SSL.dll"}" was thrown. It happens when SSLServer server = new SSLServer(); is running.
How can I fix this issue ?
Thanks.
|
|
|
|
|
You need to copy to the directory where the executable files reside (both for the client and server) the following files from the openssl/out32dll directory: libeay32.dll and ssleay32.dll
Then it should work.
|
|
|
|
|
Hi
I try to configure SSL connecting that attack man-in-the-middle would be possible. I investigated your code for set up anonymous session without authentication, but could not think out anything.
Could you help me?
|
|
|
|
|
Hi
Is the first time that I write here.
I hope you can help me.
I have a problem with deployement in SSL connection with client certificate required from IIS.
Can you help me?
Have you got some complete example code in VB.NET (from client request, to SSL connection, to server response) or other?
I need for code example (getting start) for SSL communication.
Best regards.
Nicola
When you build an application, you can't say "It work!", but you can say only "I'm not yet saw where it doesn't work"!
-- modified at 12:17 Monday 9th October, 2006
|
|
|
|
|
Hello,
I really like the code. It is very useful and performs well. However, I am experiencing it having a lot of unreleased memory. If I create an application to constantly poll the server and the memory used by the server grows very very fast. It is not collected during or after server program execution.
The problem seems to be in the managed cpp SSL.dll I have not been able to resolve this.
Can you help?
Thanks,
DK
|
|
|
|
|
I followed all the procedures and installed openssl, generated a certificate, key.etc.
when i build the solution it gives me 2 errors
The referenced component 'SSL' could not be found.
The referenced component 'SSL' could not be found.
Please could anyone guide me
Thanks in advance
Ashok
|
|
|
|
|
i got the samw prob.. can anyone help?
busyboy
|
|
|
|
|
In VS2005, the Common\SSL\Debug\ or Common\SSL\Release\ directory needs to be added to the "Reference Paths" section of each project's properties for the debug and release configurations, respectively.
|
|
|
|
|
Hi,
I am using a self signed certificate to test my application. I have un-commented the line from the sample in SSLClient.cpp
SSL_CTX_set_verify(m_pSSLCtx, SSL_VERIFY_PEER, verify_callback);
I get an error which says
7000:error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify
failed:.\ssl\s3_clnt.c:894:
What could I be missing.
I have a MS CA installed on my machine and if I run this code against the certificated generated from the CA it works fine.
Thanks in advance,
sanju
|
|
|
|
|
Hi,
I want to use this lib for ftps but for the data-connection i have to use the same ssl-session as the control connection. How can i resume this ssl-session on another socket?
I´m using the MS SSPI SSL part.
Thanks already
Azrael
|
|
|
|
|
Hi Leon,
Nice code!
I translate this code to C++, but something does not work very well. In my program, some code is from Using SSPI with a Windows Sockets Clienthttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/using_sspi_with_a_windows_sockets_client.asp[^]. I want use the SSPI implement a smtp client to connect to Gmail server. The handshake and DectryptMessage is OK. But EnctryptMessage seem to occur error. Do you have any idea about this? Here is my code:
// SSPI.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "SSPI.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
//--------------------------------------------------------------------
// Client-side program to establish an SSPI socket connection
// with a server and exchange messages.
//--------------------------------------------------------------------
// Define macros and constants.
#define SECURITY_WIN32
#define BIG_BUFF 2048
#define SEC_SUCCESS(Status) ((Status) >= 0)
#define g_usPort 465
// The following #define statement must be changed. ServerName must be
// defined as the name of the computer running the server sample.
// TargetName must be defined as the logon name of the user running
// the server program.
#define ServerName "64.233.167.111" //gmail smtp
#define TargetName "64.233.167.111"
#define cbMaxMessage 12000
#define MessageAttribute (ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |\
ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR |\
ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM)
//#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <sspi.h>
#include <schannel.h>
#include "security.h"
#ifdef __cplusplus
extern "C" {
#endif
void MyHandleError(char *s);
BOOL ConnectAuthSocket (
SOCKET *s,
CredHandle *hCred,
struct _SecHandle *hcText);
BOOL ReceiveBytes (
SOCKET s,
PBYTE pBuf,
DWORD cbBuf,
DWORD *pcbRead);
BOOL EncryptThis (
PBYTE pMessage,
ULONG cbMessage,
struct _SecHandle *hCtxt,
BYTE * pOutput,
ULONG * pcbOutput);
BOOL DecryptThis(
PBYTE pBuffer,
LPDWORD pcbMessage,
struct _SecHandle *hCtxt,
ULONG cbSecurityTrailer);
BOOL DoAuthentication (
SOCKET s,
CredHandle *hCred,
struct _SecHandle *hcText);
BOOL GenClientContext (
BYTE *pIn,
DWORD cbIn,
BYTE *pOut,
DWORD *pcbOut,
BOOL *pfDone,
CHAR *pszTarget,
CredHandle *hCred,
struct _SecHandle *hcText);
BOOL SendMsg (
SOCKET s,
PBYTE pBuf,
DWORD cbBuf);
BOOL ReceiveMsg (
SOCKET s,
PBYTE pBuf,
DWORD cbBuf,
DWORD *pcbRead);
void PrintHexDump(
DWORD length,
PBYTE buffer);
BOOL SendBytes (
SOCKET s,
PBYTE pBuf,
DWORD cbBuf);
void main()
{
SOCKET Client_Socket;
BYTE Data[BIG_BUFF];
PCHAR pMessage;
WSADATA wsaData;
CredHandle hCred;
struct _SecHandle hCtxt;
SECURITY_STATUS ss;
DWORD cbRead;
ULONG cbMaxSignature;
ULONG cbSecurityTrailer;
SecPkgContext_Sizes SecPkgContextSizes;
SecPkgContext_NegotiationInfo SecPkgNegInfo;
//-------------------------------------------------------------------
// Initialize the socket and the SSP security package.
//
if(WSAStartup (MAKEWORD( 2, 0 ), &wsaData))
{
MyHandleError("Could not initialize winsock ");
}
//--------------------------------------------------------------------
// Connect to a server
//
if (!ConnectAuthSocket (
&Client_Socket,
&hCred,
&hCtxt))
{
MyHandleError("Authenticated server connection ");
}
cbRead = recv(Client_Socket, (char*)Data, BIG_BUFF, 0);
DecryptThis(
Data,
&cbRead,
&hCtxt,
0);
printf ("The message from the server is \n -> %.*s \n", cbRead, Data);
BYTE pBuff[BIG_BUFF];// = (PBYTE) malloc(BIG_BUFF * sizeof(BYTE));
ULONG nLen = 0;
char* aCmd = "EHLO IVEN\r\n";
PBYTE pCmd = (PBYTE) malloc((strlen(aCmd) + 1) * sizeof(BYTE));
strcpy((char*)pCmd, aCmd);
EncryptThis(pCmd, 11, &hCtxt, pBuff, &nLen);
SendBytes(Client_Socket, pBuff, nLen);
BYTE csData[2048];
int len = recv(Client_Socket, (char*)csData, 2048, 0);
DecryptThis(
csData,
(LPDWORD)&len,
&hCtxt,
0);
printf ("The message from the server is \n -> %.*s \n", cbRead, Data);
//--------------------------------------------------------------------
// Terminate socket and security package.
//
DeleteSecurityContext (&hCtxt);
FreeCredentialHandle (&hCred);
shutdown (Client_Socket, 2);
closesocket (Client_Socket);
if (SOCKET_ERROR == WSACleanup ())
{
MyHandleError("Problem with socket cleanup ");
}
int x; scanf("%d", &x);
exit (EXIT_SUCCESS);
} // end main.
//--------------------------------------------------------------------
// ConnectAuthSocket establishes an authenticated socket connection
// with a server and initializes needed security package resources.
//
BOOL ConnectAuthSocket (
SOCKET *s,
CredHandle *hCred,
struct _SecHandle *hcText)
{
unsigned long ulAddress;
struct hostent *pHost;
SOCKADDR_IN sin;
//--------------------------------------------------------------------
// Lookup the server's address.
//
ulAddress = inet_addr (ServerName);
if (INADDR_NONE == ulAddress)
{
pHost = gethostbyname (ServerName);
if (NULL == pHost)
{
MyHandleError("Unable to resolve host name ");
}
memcpy((char FAR *)&ulAddress, pHost->h_addr, pHost->h_length);
}
//--------------------------------------------------------------------
// Create the socket
//
*s = socket (
PF_INET,
SOCK_STREAM,
0);
if (INVALID_SOCKET == *s)
{
MyHandleError("Unable to create socket");
}
else
{
printf("Socket created.\n");
}
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ulAddress;
sin.sin_port = htons (g_usPort);
//--------------------------------------------------------------------
// Connect to the server.
//
if (connect (*s, (LPSOCKADDR) &sin, sizeof (sin)))
{
closesocket (*s);
MyHandleError( "Connect failed ");
}
//--------------------------------------------------------------------
// Authenticate the connection.
//
if (!DoAuthentication (
*s,
hCred,
hcText))
{
closesocket (*s);
MyHandleError("Authentication ");
}
return(TRUE);
} // end ConnectAuthSocket
BOOL DoAuthentication (
SOCKET s,
CredHandle *hCred,
struct _SecHandle *hcText)
{
BOOL fDone = FALSE;
DWORD cbOut = 0;
DWORD cbIn = 0;
PBYTE pInBuf;
PBYTE pOutBuf;
if(!(pInBuf = (PBYTE) malloc(cbMaxMessage)))
{
MyHandleError("Memory allocation ");
}
if(!(pOutBuf = (PBYTE) malloc(cbMaxMessage)))
{
MyHandleError("Memory allocation ");
}
cbOut = cbMaxMessage;
if (!GenClientContext (
NULL,
0,
pOutBuf,
&cbOut,
&fDone,
TargetName,
hCred,
hcText
))
{
return(FALSE);
}
if (!SendMsg (s, pOutBuf, cbOut ))
{
MyHandleError("Send message failed ");
}
while (!fDone)
{
if (!ReceiveMsg (
s,
pInBuf,
cbMaxMessage,
&cbIn))
{
MyHandleError("Receive message failed ");
}
cbOut = cbMaxMessage;
if (!GenClientContext (
pInBuf,
cbIn,
pOutBuf,
&cbOut,
&fDone,
TargetName,
hCred,
hcText))
{
MyHandleError("GenClientContext failed");
}
if (!SendMsg (
s,
pOutBuf,
cbOut))
{
MyHandleError("Send message 2 failed ");
}
}
//MyHandleError(_T("End"));
free(pInBuf);
free(pOutBuf);
return(TRUE);
}
BOOL GenClientContext (
BYTE *pIn,
DWORD cbIn,
BYTE *pOut,
DWORD *pcbOut,
BOOL *pfDone,
CHAR *pszTarget,
CredHandle *hCred,
struct _SecHandle *hcText)
{
SECURITY_STATUS ss;
TimeStamp Lifetime;
SecBufferDesc OutBuffDesc;
SecBuffer OutSecBuff;
SecBufferDesc InBuffDesc;
SecBuffer InSecBuffs[2];
ULONG ContextAttributes;
static TCHAR lpPackageName[1024];
PSCHANNEL_CRED pSChannelCred = new SCHANNEL_CRED;
memset(pSChannelCred, 0, sizeof(SCHANNEL_CRED));
pSChannelCred->dwVersion = SCHANNEL_CRED_VERSION;
pSChannelCred->grbitEnabledProtocols = SP_PROT_NONE;
pSChannelCred->dwFlags |= SCH_CRED_NO_DEFAULT_CREDS|SCH_CRED_MANUAL_CRED_VALIDATION;
if( NULL == pIn )
{
lstrcpy(lpPackageName, UNISP_NAME_A);
ss = AcquireCredentialsHandle (
NULL,
UNISP_NAME_A,
SECPKG_CRED_OUTBOUND,
NULL,
pSChannelCred,
NULL,
NULL,
hCred,
&Lifetime);
if (!(SEC_SUCCESS (ss)))
{
MyHandleError("AcquireCreds failed ");
}
}
delete pSChannelCred;
//--------------------------------------------------------------------
// Prepare the buffers
//
OutBuffDesc.ulVersion = 0;
OutBuffDesc.cBuffers = 1;
OutBuffDesc.pBuffers = &OutSecBuff;
OutSecBuff.cbBuffer = *pcbOut;
OutSecBuff.BufferType = SECBUFFER_TOKEN;
OutSecBuff.pvBuffer = NULL;
//-------------------------------------------------------------------
// The input buffer is created only if a message has been received from the server.
//
if (pIn)
{
InBuffDesc.ulVersion = 0;
InBuffDesc.cBuffers = 2;
InBuffDesc.pBuffers = InSecBuffs;
InSecBuffs[0].cbBuffer = cbIn;
InSecBuffs[0].BufferType = SECBUFFER_TOKEN;
InSecBuffs[0].pvBuffer = pIn;
InSecBuffs[1].cbBuffer = 0;
InSecBuffs[1].BufferType = SECBUFFER_EMPTY;
InSecBuffs[1].pvBuffer = NULL;
ss = InitializeSecurityContext (
hCred,
hcText,
NULL,
MessageAttribute,
0,
SECURITY_NATIVE_DREP,
&InBuffDesc,
0,
hcText,
&OutBuffDesc,
&ContextAttributes,
&Lifetime);
}
else
{
ss = InitializeSecurityContext (
hCred,
NULL,
"64.233.167.111",/*pszTarget,*/
MessageAttribute,
0,
SECURITY_NATIVE_DREP,
NULL,
0,
hcText,
&OutBuffDesc,
&ContextAttributes,
&Lifetime);
//pOut = static_cast<byte*>(OutBuffDesc.pBuffers->pvBuffer);
}
memcpy(pOut, OutBuffDesc.pBuffers->pvBuffer, OutBuffDesc.pBuffers->cbBuffer);
if (!SEC_SUCCESS (ss))
{
MyHandleError ("InitializeSecurityContext failed " );
}
//-------------------------------------------------------------------
// If necessary, complete the token.
//
if ((SEC_I_COMPLETE_NEEDED == ss)
|| (SEC_I_COMPLETE_AND_CONTINUE == ss))
{
ss = CompleteAuthToken (hcText, &OutBuffDesc);
if (!SEC_SUCCESS(ss))
{
fprintf (stderr, "complete failed: 0x%08x\n", ss);
return FALSE;
}
}
*pcbOut = OutSecBuff.cbBuffer;
*pfDone = !((SEC_I_CONTINUE_NEEDED == ss) ||
(SEC_I_COMPLETE_AND_CONTINUE == ss));
printf ("Token buffer generated (%lu bytes):\n", OutSecBuff.cbBuffer);
PrintHexDump (OutSecBuff.cbBuffer, (PBYTE)OutSecBuff.pvBuffer);
return TRUE;
}
BOOL EncryptThis (
PBYTE pMessage,
ULONG cbMessage,
struct _SecHandle *hCtxt,
BYTE * pOutput,
ULONG * pcbOutput)
{
SECURITY_STATUS ss;
SecBufferDesc BuffDesc;
SecBuffer SecBuff[4];
ULONG SigBufferSize;
char* pInBuf;
SecPkgContext_StreamSizes szStream;
ss = QueryContextAttributes(hCtxt, SECPKG_ATTR_STREAM_SIZES, &szStream);
if (!SEC_SUCCESS(ss))
{
fprintf (stderr, "QueryContextAttributes faild: 0x%08x\n", ss);
return(FALSE);
}
SigBufferSize = szStream.cbMaximumMessage + szStream.cbHeader + szStream.cbTrailer;
pInBuf = (char*) malloc(SigBufferSize);
if (!pInBuf)
{
printf(_T("Memery over erro!\r\n"));
exit (EXIT_FAILURE);
}
memcpy(pInBuf + szStream.cbHeader, pMessage, cbMessage);
printf ("Data before encryption: %s\n", pMessage);
printf ("Length of data before encryption: %d \n",cbMessage);
//------------------------------------------------------------------
// Prepare buffers
//
BuffDesc.ulVersion = 0;
BuffDesc.cBuffers = 4;
BuffDesc.pBuffers = SecBuff;
SecBuff[0].cbBuffer = szStream.cbHeader;
SecBuff[0].BufferType = SECBUFFER_STREAM_HEADER;
SecBuff[0].pvBuffer = pInBuf;
SecBuff[1].cbBuffer = cbMessage;
SecBuff[1].BufferType = SECBUFFER_DATA;
SecBuff[1].pvBuffer = pInBuf + szStream.cbHeader;
SecBuff[2].cbBuffer = szStream.cbTrailer;
SecBuff[2].BufferType = SECBUFFER_STREAM_TRAILER;
SecBuff[2].pvBuffer = pInBuf + szStream.cbHeader + szStream.cbTrailer;
SecBuff[3].cbBuffer = 0;
SecBuff[3].BufferType = SECBUFFER_EMPTY;
SecBuff[3].pvBuffer = NULL;
ss = EncryptMessage(
hCtxt,
0,
&BuffDesc,
0);
if (!SEC_SUCCESS(ss))
{
fprintf (stderr, "EncryptMessage failed: 0x%08x\n", ss);
return(FALSE);
}
else
{
printf("The message has been encrypted. \n");
}
*pcbOutput = SecBuff[0].cbBuffer + SecBuff[1].cbBuffer + SecBuff[2].cbBuffer;
memcpy (pOutput, pInBuf, *pcbOutput);
free(pInBuf);
printf ("data after encryption including trailer (%lu bytes):\n", *pcbOutput);
PrintHexDump (*pcbOutput, pOutput);
return TRUE;
} // end EncryptThis
BOOL DecryptThis(
PBYTE pBuffer,
LPDWORD pcbMessage,
struct _SecHandle *hCtxt,
ULONG cbSecurityTrailer)
{
BOOL bRet = FALSE;
SECURITY_STATUS ss;
SecBufferDesc BuffDesc;
SecBuffer SecBuff[4];
ULONG ulQop = 0;
PBYTE pSigBuffer;
void* pDataBuffer;
DWORD SigBufferSize;
//-------------------------------------------------------------------
// By agreement, the server encrypted the message and set the size
// of the trailer block to be just what it needed. DecryptMessage
// needs the size of the trailer block.
// The size of the trailer is in the first dword of the
// message received.
//
SigBufferSize = *pcbMessage;
printf ("data before decryption including trailer (%lu bytes):\n",
*pcbMessage);
PrintHexDump (*pcbMessage, (PBYTE) pBuffer);
//--------------------------------------------------------------------
// By agreement, the server placed the trailer at the beginning
// of the message sent right after the trailer size dword.
pSigBuffer = pBuffer;
//--------------------------------------------------------------------
// The data comes after the trailer.
//
//pDataBuffer = pSigBuffer;
//--------------------------------------------------------------------
// *pcbMessage is reset to the size of just the encrypted bytes.
//
//*pcbMessage = *pcbMessage - SigBufferSize - sizeof(DWORD);
//--------------------------------------------------------------------
// Prepare the buffers to be passed to the DecyrptMessage function.
//
BuffDesc.ulVersion = 0;
BuffDesc.cBuffers = 4;
BuffDesc.pBuffers = SecBuff;
SecBuff[0].cbBuffer = SigBufferSize;
SecBuff[0].BufferType = SECBUFFER_DATA;
SecBuff[0].pvBuffer = pSigBuffer;
SecBuff[1].cbBuffer = 0;
SecBuff[1].BufferType = SECBUFFER_EMPTY;
SecBuff[1].pvBuffer = NULL;
SecBuff[2].cbBuffer = 0;
SecBuff[2].BufferType = SECBUFFER_EMPTY;
SecBuff[2].pvBuffer = NULL;
SecBuff[3].cbBuffer = 0;
SecBuff[3].BufferType = SECBUFFER_EMPTY;
SecBuff[3].pvBuffer = NULL;
ss = DecryptMessage(
hCtxt,
&BuffDesc,
0,
NULL/*&ulQop*/);
if (!SEC_SUCCESS(ss))
{
fprintf(stderr, "DecryptMessage failed");
}
//-------------------------------------------------------------------
// Return a pointer to the decrypted data. The trailer data
// is discarded.
for(int i = 1; i < 4; i++)
{
if (SecBuff[i].BufferType == SECBUFFER_DATA)
{
pDataBuffer = SecBuff[i].pvBuffer;
*pcbMessage = bRet = SecBuff[i].cbBuffer;
break;
}
}
memcpy(pBuffer, pDataBuffer, bRet);
return bRet;
}
PBYTE VerifyThis(
PBYTE pBuffer,
LPDWORD pcbMessage,
struct _SecHandle *hCtxt,
ULONG cbMaxSignature)
{
SECURITY_STATUS ss;
SecBufferDesc BuffDesc;
SecBuffer SecBuff[2];
ULONG ulQop = 0;
PBYTE pSigBuffer;
PBYTE pDataBuffer;
//-------------------------------------------------------------------
// The global cbMaxSignature is the size of the signature
// in the message received.
printf ("data before verifying (including signature):\n");
PrintHexDump (*pcbMessage, pBuffer);
//--------------------------------------------------------------------
// By agreement with the server,
// the signature is at the beginning of the message received
// and the data that was signed comes after the signature.
//
pSigBuffer = pBuffer;
pDataBuffer = pBuffer + cbMaxSignature;
//-------------------------------------------------------------------
// The size of the message is reset to the size of the data only.
//
*pcbMessage = *pcbMessage - (cbMaxSignature);
//--------------------------------------------------------------------
// Prepare the buffers to be passed to the signature verification
// function.
//
BuffDesc.ulVersion = 0;
BuffDesc.cBuffers = 2;
BuffDesc.pBuffers = SecBuff;
SecBuff[0].cbBuffer = cbMaxSignature;
SecBuff[0].BufferType = SECBUFFER_TOKEN;
SecBuff[0].pvBuffer = pSigBuffer;
SecBuff[1].cbBuffer = *pcbMessage;
SecBuff[1].BufferType = SECBUFFER_DATA;
SecBuff[1].pvBuffer = pDataBuffer;
ss = VerifySignature(
hCtxt,
&BuffDesc,
0,
&ulQop
);
if (!SEC_SUCCESS(ss))
{
fprintf(stderr, "VerifyMessage failed");
}
else
{
printf("Message was properly signed.\n");
}
return pDataBuffer;
}// end VerifyThis
void PrintHexDump(
DWORD length,
PBYTE buffer)
{
DWORD i,count,index;
CHAR rgbDigits[]="0123456789abcdef";
CHAR rgbLine[100];
char cbLine;
for(index = 0; length; length -= count, buffer += count, index += count)
{
count = (length > 16) ? 16:length;
sprintf(rgbLine, "%4.4x ",index);
cbLine = 6;
for(i=0;i<count;i++)
="" {
="" rgbline[cbline++]="rgbDigits[buffer[i]">> 4];
rgbLine[cbLine++] = rgbDigits[buffer[i] & 0x0f];
if(i == 7)
{
rgbLine[cbLine++] = ':';
}
else
{
rgbLine[cbLine++] = ' ';
}
}
for(; i < 16; i++)
{
rgbLine[cbLine++] = ' ';
rgbLine[cbLine++] = ' ';
rgbLine[cbLine++] = ' ';
}
rgbLine[cbLine++] = ' ';
for(i = 0; i < count; i++)
{
if(buffer[i] < 32 || buffer[i] > 126)
{
rgbLine[cbLine++] = '.';
}
else
{
rgbLine[cbLine++] = buffer[i];
}
}
rgbLine[cbLine++] = 0;
printf("%s\n", rgbLine);
}
}
BOOL SendMsg (
SOCKET s,
PBYTE pBuf,
DWORD cbBuf)
{
if (0 == cbBuf)
return(TRUE);
//----------------------------------------------------------
// Send the size of the message.
//
//if (!SendBytes (s, (PBYTE)&cbBuf, sizeof (cbBuf)))
// return(FALSE);
//----------------------------------------------------------
// Send the body of the message.
//
if (!SendBytes (
s,
pBuf,
cbBuf))
{
return(FALSE);
}
return(TRUE);
}
BOOL ReceiveMsg (
SOCKET s,
PBYTE pBuf,
DWORD cbBuf,
DWORD *pcbRead)
{
DWORD cbRead;
DWORD cbData;
if (!ReceiveBytes (
s,
pBuf,
cbBuf,
&cbRead))
{
return(FALSE);
}
//if (cbRead != cbData)
// return(FALSE);
*pcbRead = cbRead;
return(TRUE);
} // end ReceiveMessage
BOOL SendBytes (
SOCKET s,
PBYTE pBuf,
DWORD cbBuf)
{
PBYTE pTemp = pBuf;
int cbSent;
int cbRemaining = cbBuf;
if (0 == cbBuf)
return(TRUE);
while (cbRemaining)
{
cbSent = send (
s,
(const char *)pTemp,
cbRemaining,
0);
if (SOCKET_ERROR == cbSent)
{
fprintf (stderr, "send failed: %u\n", GetLastError ());
return FALSE;
}
pTemp += cbSent;
cbRemaining -= cbSent;
}
return TRUE;
}
BOOL ReceiveBytes (
SOCKET s,
PBYTE pBuf,
DWORD cbBuf,
DWORD *pcbRead)
{
PBYTE pTemp = pBuf;
int cbRead, cbRemaining = cbBuf;
//while (cbRemaining)
{
cbRead = recv (
s,
(char *)pTemp,
cbRemaining,
0);
if (SOCKET_ERROR == cbRead)
{
fprintf (stderr, "recv failed: %u\n", GetLastError ());
return FALSE;
}
cbRemaining -= cbRead;
pTemp += cbRead;
}
*pcbRead = cbBuf - cbRemaining;
return TRUE;
} // end ReceiveBytes
void MyHandleError(char *s)
{
fprintf(stderr,"%s error. Exiting.\n",s);
int x; scanf("%d", &x);
exit (EXIT_FAILURE);
}
#ifdef __cplusplus
}
#endif
|
|
|
|
|
Hi Leon
First, thanks for the great article. This is the best article I've seen on SSPI for communicating with SSL with sockets. Anyway, this code , we have been using since 1 year with out any problems. But recently we encountered a problem.
When I am trying to read from a server response, we could able to read the complete message most of the times and able to get the SEC_E_OK, but few times we are getting SEC_I_CONTEXT_EXPIRED even after reading the complete data from the server. After analyzing the case, I came to a conclusion that due the extra buffers and SEC_I_CONTEXT_ EXPIRED, we are getting the Decryption Failed. Context Expired message.
And it is clear that server is closing the connection after sending the data.
Do you have any suggestion or correction to address the above issue?
Please help me.
Thanks & Regards
Shaik
|
|
|
|
|