|
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
|
|
|
|
|
First off, I want to thank you very much for the .Net C++ wrapper classes that you have created.
I have created a TCP Server and TCP Client library that basically shims in calls to the Microsoft SSP .Net C++ wrapper classes when the required connection is a secure connection. This all works great when I use the TCP Client library to talk to the TCP Server library.
My need is to have a Verifone Terminal connect up to a Terminal application server using my TCP Server library and I am receiving a SEC_E_ALGORITHM_MISMATCH 0x80090331 error.
To give you a little history, the previous Terminal application server was written in TCL (ugh) and it integrated with a TCL wrapper to the OpenSource SSL libraries. The Verifone Terminal supports OpenSource libraries and it appears to only support a single cipher.
This works fine:
When I look at the Client Hello message for a TCP Client that is using your Microsoft SSP .Net C++ wrapper class, I noticed that the Client Hello message was sent in the SSL 2.0 format, but stated that the version of SSL supported was 3.1. The SSL 2.0 format starts with 2 bytes that represent the length of the message, followed by the client hello identifier (1), followed by SSL Version (31), followed by the length of the ciphers (51 which is 17 ciphers), followed by length of sessionID (0), followed by length of challenge data (16), followed by the 17 ciphers (3 bytes for each cipher in SSL 2.0), followed by the 16 bytes of challenge data. I thought it was odd that the hello client was not sent in the SSL 3 / 3.1 format, but everything worked just fine.
This doesn't work:
When I look at the Client Hello message from the Verifone terminal, it was sent in the SSL 3.0 format. This format starts with 1 byte that represents the component type which is a handshake (22), followed by two bytes for SSL version (30), followed by two bytes for the length of the rest of the message (45), followed by handshake type (1) which is the client hello, followed by 3 bytes which represents the length of the client hello message (41), followed by 32 bytes of random numbers generated by the client, followed by length of sessionID (0), followed by length of cipher (2), followed by a single cipher (04), followed by length of compression (1), followed by compression value (0).
The format of the client hello message looks correct and it works with the TCL server that uses the OpenSource libraries just fine. The certificate was generated by the OpenSSL utility (PEM and privatekey). If the format of the client hello message was rejected by the Microsoft SSP AcceptSecurityContext call, I believe I would have received the following error, SEC_E_INVALID_TOKEN
0x80090308. The SEC_E_ALGORITHM_MISMATCH error appears to be that Microsoft SSP AcceptSecurityContext doesn't support the one cipher suite that the Verifone terminal is sending in its client hello; more on this in the next paragraph.
The cipher 0x00, 0x04 is the SSL_RSA_WITH_RC4_128_MD5 cipher suite. I believe this matches the 3 byte cipher 0x01, 0x00, 0x80 that was sent as one of the 17 cipher suites by the TCP Client using your wrapper library in the SSL 2.0 format. My thoughts are that the Microsoft SSP decided to use one of the other 17 cipher suites to communicate with the TCP Client that actually is working and it is rejecting the only cipher suite sent from the Verifone terminal SSL_RSA_WITH_RC4_128_MD5. The thing that has me puzzled is that the SSL_RSA_WITH_RC4_128_MD5 cipher suite is a pretty common one, right?
I've researched this problem for a couple of days now and am stuck. In the meantime, I will be integrating your OpenSSL wrapper and see if this does the trick, but I would rather use the Microsoft SSP wrapper if at all possible.
Thanks in advance,
Larry Herbinaux
|
|
|
|
|
The issue was that my SSLServer was set to only allow the TLS1 protocol. I added another enumeration value to the protocol enumeration defined in SSLCommon.h called SSL3_OR_TLS1 which just combinds the two enumeration values which are just bit mask values passed into the AcquireCredentialsHandleA method to allow SSL3 or TLS1 for both Client and Server. I initially set the protocol to SSL3 to determine that my problem was indeed the protocol bit flags and this dialed down my SSL Client from 3.1 to 3.0. I figured that it is best to set all the bit flags so that TLS clients don't necessarily get downgraded to 3.0.
The next problem that I ran into was that my certificate has both a Trusted Root and an Intermediate CA. The Microsoft SSP library sends the following handshake messages in a single SSL encrypted digest (ServerHello, Certificate, ServerHelloDone). The contents of the digest were 2396 bytes in length and the Verifone terminal has a problem processing more than 1024 bytes at a time. I was able to generate a self-signed SSL certificate and the SSL digest was reduced to 998 bytes, so the SSL handshake now works between the Verifone Terminal client and the Microsoft SSP implementation. I would rather not generate a self-signed certificate. Is there a way to send each of the handshake messages (ServerHello, Certificate, and ServerHelloDone) in separate SSL digests? Is there a way to only send the certificate without the chained CA certificates? The Verifone terminal doesn't validate the chained CA certificates (i.e. they don't store these on the terminal). The reason why I ask the questions above is due to some observations I had while analyzing the packets between the TCL OpenSSL Server and the Verifone terminal; see below.
The original TCL SSL (OpenSSL) server used a self-generated SSL Certificate, so the size of the certificate is smaller than the certificate chain above. The OpenSSL library appears to separate the (ServerHello, Certificate, and ServerHelloDone) messages into two separate SSL digests; they were around 500 and 400 bytes respectively. Another interesting fact is that I decided to generate a .PEM from my .cer of my chained certificate and when we had the TCL OpenSSL server use this .PEM, the size of the two handshake messages above were relatively the same. I expected the size on one of them to increase dramatically. This leads me to believe that the TCL OpenSSL server is just passing down the certificate to the Verifone client and does not additionally send the chained CA certificates.
|
|
|
|
|