mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
499 lines
13 KiB
499 lines
13 KiB
#define WSSA_DEBUG
|
|
/*Included Files------------------------------------------------------------*/
|
|
#include "ssldbg.h" //#include <assert.h>
|
|
#include <malloc.h>
|
|
#include "ssl.h"
|
|
#include "guts.h"
|
|
#include "table.h"
|
|
|
|
#ifdef DBG
|
|
void _AssertFailedSz(LPCSTR pszText,LPCSTR pszFile, int line)
|
|
{
|
|
LPCSTR psz;
|
|
char ach[256];
|
|
static char szAssertFailed[] = "NTIE(SSL): %s (%s,line %d)\r\n";
|
|
|
|
if (AppZoneMask & DBG_SPM)
|
|
{
|
|
for (psz = pszFile + lstrlen(pszFile); psz != pszFile; psz=AnsiPrev(pszFile,psz))
|
|
{
|
|
if ((AnsiPrev(pszFile, psz)!= (psz-2)) && *(psz - 1) == '\\')
|
|
break;
|
|
}
|
|
wsprintf(ach, szAssertFailed, pszText,psz, line);
|
|
OutputDebugString(ach);
|
|
}
|
|
}
|
|
|
|
void cdecl _DebugMsgSsl(LPCSTR pszMsg, ...)
|
|
{
|
|
char ach[2*MAX_PATH+40];
|
|
va_list ArgList;
|
|
|
|
if (AppZoneMask & DBG_SPM)
|
|
{
|
|
va_start(ArgList, pszMsg);
|
|
wvsprintf(ach, pszMsg, ArgList);
|
|
OutputDebugString("NTIE(SSL): ");
|
|
OutputDebugString(ach);
|
|
OutputDebugString("\r\n");
|
|
va_end(ArgList);
|
|
}
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
/*Quick Debugging Macro-----------------------------------------------------*/
|
|
#define VAR_SSI(varname, from) SSI varname = WssaTableGetSSI(from)
|
|
static int gOne = 1;
|
|
static int gZero = 0;
|
|
|
|
/*Boring Downcalls----------------------------------------------------------*/
|
|
int WSSAFNCT WssaBind(SECURE_SOCKET ss, const struct sockaddr FAR *addr, int namelen){
|
|
int retval;
|
|
|
|
DebugEntry(WssaBind);
|
|
retval = bind(SS2S(ss),addr,namelen);
|
|
DebugExitINT(WssaBind, retval);
|
|
return(retval);
|
|
}
|
|
|
|
int WSSAFNCT WssaIoctlSocket(SECURE_SOCKET ss, long cmd, u_long FAR *argp){
|
|
int retval;
|
|
|
|
DebugEntry(WssaIoctlSocket);
|
|
|
|
retval = ioctlsocket(SS2S(ss),cmd,argp);
|
|
|
|
DebugExitINT(WssaIoctlSocket, retval);
|
|
return(retval);
|
|
}
|
|
|
|
int WSSAFNCT WssaGetPeerName(SECURE_SOCKET ss, struct sockaddr FAR *name, int FAR * namelen){
|
|
int retval;
|
|
|
|
DebugEntry(WssaGetPeerName);
|
|
|
|
retval = getpeername(SS2S(ss), name,namelen);
|
|
DebugExitINT(WssaGetPeerName, retval);
|
|
return(retval);
|
|
// return getpeername(SS2S(ss), name,namelen);
|
|
}
|
|
|
|
int WSSAFNCT WssaGetSocketName (SECURE_SOCKET ss, struct sockaddr FAR *name, int FAR * namelen){
|
|
int retval;
|
|
|
|
DebugEntry(WssaGetSocketName);
|
|
|
|
retval = getsockname(SS2S(ss), name,namelen);
|
|
DebugExitINT(WssaGetSocketName, retval);
|
|
return(retval);
|
|
// return getsockname(SS2S(ss), name,namelen);
|
|
}
|
|
|
|
int WSSAFNCT WssaListen(SECURE_SOCKET ss, int backlog){
|
|
int retval;
|
|
|
|
DebugEntry(WssaListen);
|
|
|
|
retval = listen(SS2S(ss),backlog);
|
|
DebugExitINT(WssaListen, retval);
|
|
return(retval);
|
|
// return listen(SS2S(ss),backlog);
|
|
}
|
|
|
|
int WSSAFNCT WssaShutdown(SECURE_SOCKET ss, int how){
|
|
int retval;
|
|
|
|
DebugEntry(WssaShutdown);
|
|
|
|
retval = shutdown(SS2S(ss),how);
|
|
DebugExitINT(WssaShutdown, retval);
|
|
return(retval);
|
|
// return shutdown(SS2S(ss),how);
|
|
}
|
|
|
|
int WSSAFNCT WssaConnect(SECURE_SOCKET ss, const struct sockaddr FAR *name, int namelen){
|
|
int retval;
|
|
|
|
DebugEntry(WssaConnect);
|
|
retval = connect(SS2S(ss),name,namelen);
|
|
DebugExitINT(WssaConnect, retval);
|
|
return(retval);
|
|
// return connect(SS2S(ss),name,namelen);
|
|
}
|
|
|
|
int WSSAFNCT WssaAsyncSelect(SECURE_SOCKET ss, HWND hWnd, unsigned int wMsg, long lEvent){
|
|
int retval;
|
|
|
|
// DebugEntry(WssaAsyncSelect);
|
|
TRACE_OUT("WssaAsyncSelect(0x%x, 0x%x, 0x%x, 0x%lx)", ss, hWnd, wMsg, lEvent);
|
|
|
|
retval = WSAAsyncSelect(SS2S(ss), hWnd, wMsg, lEvent);
|
|
DebugExitINT(WssaAsyncSelect, retval);
|
|
return(retval);
|
|
// return WSAAsyncSelect(SS2S(ss), hWnd, wMsg, lEvent);
|
|
}
|
|
|
|
SECURE_SOCKET WSSAFNCT WssaAccept(SECURE_SOCKET ssIn, struct sockaddr FAR *addr,int FAR *addrlen){
|
|
#ifdef WSSA_SERVER
|
|
VAR_SSI(ssiIn,ssIn);
|
|
SSI ssi;
|
|
SECURE_SOCKET ss;
|
|
|
|
ss = (SECURE_SOCKET) accept(SS2S(ssIn),addr,addrlen);
|
|
if (INVALID_SOCKET != ss) {
|
|
ssi = DuplicateAndInstallSSI(ssIn, ssiIn);
|
|
if (NULL == ssi){
|
|
WssaCloseSocket(ss);
|
|
WSASetLastError(WSSA_ERROR_NO_MEM);
|
|
ss = INVALID_SOCKET;
|
|
}
|
|
}
|
|
return ss;
|
|
#else
|
|
SECURE_SOCKET retval;
|
|
|
|
DebugEntry(WssaAccept);
|
|
|
|
retval = (SECURE_SOCKET) accept(SS2S(ssIn),addr,addrlen);
|
|
DebugExitINT(WssaAccept, retval);
|
|
return(retval);
|
|
// return (SECURE_SOCKET) accept(SS2S(ssIn),addr,addrlen);
|
|
#endif
|
|
}
|
|
|
|
SECURE_SOCKET WSSAFNCT WssaSocket(int af, int type, int protocol){
|
|
SECURE_SOCKET retval;
|
|
|
|
DebugEntry(WssaSocket);
|
|
|
|
retval = (SECURE_SOCKET) socket(af,type,protocol);
|
|
|
|
DebugExitINT(WssaSocket, retval);
|
|
return(retval);
|
|
// return (SECURE_SOCKET) socket(af,type,protocol);
|
|
}
|
|
|
|
int WSSAFNCT WssaSendTo(SECURE_SOCKET ss, const char FAR * buf, int len, int flags, const struct sockaddr FAR *to, int tolen){
|
|
int retval;
|
|
|
|
DebugEntry(WssaSendTo);
|
|
|
|
retval = sendto(SS2S(ss),buf,len,flags,to,tolen);
|
|
|
|
DebugExitINT(WssaSendTo, retval);
|
|
return(retval);
|
|
// return sendto(SS2S(ss),buf,len,flags,to,tolen);
|
|
}
|
|
|
|
int WSSAFNCT WssaReceiveFrom(SECURE_SOCKET ss, char FAR * buf, int len, int flags, struct sockaddr FAR *from, int FAR * fromlen){
|
|
int retval;
|
|
|
|
DebugEntry(WssaReceiveFrom);
|
|
|
|
retval = recvfrom(SS2S(ss),buf,len,flags,from,fromlen);
|
|
DebugExitINT(WssaReceiveFrom, retval);
|
|
return(retval);
|
|
// return recvfrom(SS2S(ss),buf,len,flags,from,fromlen);
|
|
}
|
|
|
|
|
|
/*Slightly Interesting Overloads--------------------------------------------*/
|
|
int WSSAFNCT WssaCloseSocket(SECURE_SOCKET ss){
|
|
int retval;
|
|
VAR_SSI(ssi,ss);
|
|
|
|
DebugEntry(WssaCloseSocket);
|
|
|
|
if (NULL != ssi) DestructSSI(ssi);
|
|
WssaTableRemoveEntry(ss);
|
|
retval = closesocket(SS2S(ss));
|
|
DebugExitINT(WssaCloseSocket, retval);
|
|
return(retval);
|
|
}
|
|
|
|
|
|
int WSSAFNCT WssaReceive(SECURE_SOCKET ss, char FAR * buf, int len, int flags)
|
|
{
|
|
VAR_SSI(ssi,ss);
|
|
BOOL fSecurity = FALSE;
|
|
int errno, retval;
|
|
|
|
DebugEntry(WssaReceive);
|
|
|
|
/*receive data*/
|
|
if (NULL != ssi)
|
|
{
|
|
/*do handshake!?!*/
|
|
if ( !(ssi->dwSSLSystemFlags & WSSA_FLAG_HANDSHAKE_DONE)
|
|
&& (ssi->dwSSLUserFlags & SO_SSL_ENABLE)
|
|
&& (ssi->dwSSLUserFlags & SO_SSL_SERVER)
|
|
)
|
|
{
|
|
/*yes*/
|
|
errno = SslHandshakeAsServer(ss);
|
|
if (SOCKET_ERROR == errno)
|
|
{
|
|
DebugExitINT(WssaReceiveSOCKET_ERROR, errno);
|
|
return SOCKET_ERROR;
|
|
}
|
|
}
|
|
if (ssi->dwSSLSystemFlags & WSSA_FLAG_ENCRYPTION_ON)
|
|
{
|
|
/*encrypted*/
|
|
retval = SslReceiveAndUnPack(ss, &fSecurity, buf, &len,flags);
|
|
DebugExitINT(WssaReceiveENCRYPT, retval);
|
|
return(retval);
|
|
}
|
|
}
|
|
/*plain*/
|
|
|
|
retval = recv(SS2S(ss),buf,len,flags);
|
|
DebugExitINT(WssaReceive, retval);
|
|
return(retval);
|
|
}
|
|
|
|
int WSSAFNCT WssaSend(SECURE_SOCKET ss, const char FAR * buf, int len, int flags){
|
|
VAR_SSI(ssi,ss);
|
|
int errno, retval;
|
|
|
|
DebugEntry(WssaSend);
|
|
|
|
/*Send Data*/
|
|
if (NULL != ssi){
|
|
/*do handshake!?!*/
|
|
if ( !(ssi->dwSSLSystemFlags & WSSA_FLAG_HANDSHAKE_DONE)
|
|
&& (ssi->dwSSLUserFlags & SO_SSL_ENABLE)
|
|
&& !(ssi->dwSSLUserFlags & SO_SSL_SERVER)
|
|
){
|
|
/*yes*/
|
|
errno = SslHandshakeAsClient(ss);
|
|
|
|
if (SOCKET_ERROR == errno)
|
|
{
|
|
DebugExitINT(WssaSend, errno);
|
|
return SOCKET_ERROR;
|
|
}
|
|
// if we've completed the handshake, we must now
|
|
// let the upper layers check to see that we've gotten
|
|
// a solid cert. with valid date/time and CN.
|
|
if ( (ssi->dwSSLSystemFlags & WSSA_FLAG_HANDSHAKE_DONE) )
|
|
{
|
|
DebugExitINT(WssaSendWSSA_FLAG_HANDSHAKE_DONE, SOCKET_ERROR);
|
|
return SOCKET_ERROR;
|
|
}
|
|
}
|
|
if (ssi->dwSSLSystemFlags & WSSA_FLAG_ENCRYPTION_ON){
|
|
/*encrypted*/
|
|
if ( len > (SSL_MAX_RECORD_LENGTH_2_BYTE_HEADER - WSSA_MAGIC_PREPAD) )
|
|
len = (SSL_MAX_RECORD_LENGTH_2_BYTE_HEADER - WSSA_MAGIC_PREPAD);
|
|
retval= SslPackAndSend(ss, (char*) buf, len, FALSE, FALSE);
|
|
DebugExitINT(WssaSendWSSA_FLAG_ENCRYPTION_ON, retval);
|
|
return(retval);
|
|
}
|
|
}
|
|
/*plain*/
|
|
retval = send(SS2S(ss),buf,len,flags);
|
|
DebugExitINT(WssaSend, retval);
|
|
return(retval);
|
|
}
|
|
|
|
|
|
#define DWORD_SOCKOPT_SET(optname, varname) \
|
|
case optname:\
|
|
varname = (DWORD) optval;\
|
|
DebugExitINT(WssaSetSocketOption, !SOCKET_ERROR); \
|
|
return (!SOCKET_ERROR);
|
|
|
|
#define PC_SOCKOPT_SET(optname, varname, varsize) \
|
|
case optname :\
|
|
if (*optlen > varsize){\
|
|
Free(ssi->varname);\
|
|
ssi->varname = malloc(*optlen);\
|
|
if (NULL == ssi->varname) { \
|
|
DebugExitINT(WssaSetSocketOption, WSAEFAULT); \
|
|
return WSAEFAULT;\
|
|
} \
|
|
}\
|
|
ssi->varsize = *optlen;\
|
|
memcpy(ssi->varname, optval, *optlen);\
|
|
DebugExitINT(WssaSetSocketOption, !SOCKET_ERROR); \
|
|
return (!SOCKET_ERROR);
|
|
|
|
#define RG_SOCKOPT_SET(optname, varname) \
|
|
case optname: \
|
|
memcpy(varname, optval, optlen);\
|
|
DebugExitINT(WssaSetSocketOption, !SOCKET_ERROR); \
|
|
return (!SOCKET_ERROR);
|
|
|
|
int WSSAFNCT WssaSetSocketOption(SECURE_SOCKET ss, int level, int optname, const char FAR * optval, int optlen){
|
|
VAR_SSI(ssi,ss);
|
|
int retval;
|
|
|
|
DebugEntry(WssaSetSocketOption);
|
|
TRACE_OUT(" ss=0x%x", ss);
|
|
|
|
/*Is this a new option category?*/
|
|
if (SO_SSL_LEVEL == level)
|
|
{
|
|
/*make ssi if we don't have one*/
|
|
if (NULL == ssi) ssi = ConstructSSI(ss);
|
|
if (NULL != ssi){
|
|
/*yes*/
|
|
switch (optname){
|
|
DWORD_SOCKOPT_SET(SO_SSL_FLAGS, ssi->dwSSLUserFlags);
|
|
DWORD_SOCKOPT_SET(SO_SSL_CERTIFICATE_TYPE, ssi->nCertificateType);
|
|
case SO_SSL_HOSTNAME :
|
|
if (ssi->pszHostName != NULL){
|
|
Free(ssi->pszHostName);
|
|
}
|
|
ssi->pszHostName = malloc(optlen);
|
|
if (NULL == ssi->pszHostName) return WSAEFAULT;
|
|
memcpy(ssi->pszHostName, optval, optlen);
|
|
DebugExitINT(WssaSetSocketOption, !SOCKET_ERROR);
|
|
return (!SOCKET_ERROR);
|
|
|
|
/*
|
|
PC_SOCKOPT_GET(SO_SSL_CERTIFICATE, pCertificateData, ssi->nCertificateSize);
|
|
PC_SOCKOPT_GET(SO_SSL_SESSION_ID_DATA, rgSessionIdData, ssi->nSessionIdSize);
|
|
PC_SOCKOPT_GET(SO_SSL_CIPHER_SPECS, pCipherSpecData, ssi->nCipherSpecSize);
|
|
*/
|
|
RG_SOCKOPT_SET(SO_SSL_STATE_INFO, &ssi->nSessionIdSize);
|
|
}
|
|
}
|
|
else return SOCKET_ERROR;
|
|
}
|
|
/*drop down to base case*/
|
|
retval= setsockopt(SS2S(ss),level,optname,optval,optlen);
|
|
DebugExitINT(WssaSetSocketOption, retval);
|
|
return(retval);
|
|
}
|
|
|
|
#define DWORD_SOCKOPT_GET(optname, varname)\
|
|
case optname: \
|
|
TRACE_OUT( #optname ); \
|
|
*((DWORD*) optval) = ssi?varname:0;\
|
|
*optlen=4;\
|
|
DebugExitINT(WssaGetSocketOption, *optval); \
|
|
return 0;
|
|
|
|
#define PC_SOCKOPT_GET(optname, varname, varsize)\
|
|
case optname :\
|
|
TRACE_OUT( #optname ); \
|
|
if (ssi){\
|
|
if (*optlen < varsize){\
|
|
*optlen = varsize;\
|
|
DebugExitINT(WssaGetSocketOption, WSAEFAULT); \
|
|
return WSAEFAULT;\
|
|
}\
|
|
*optlen = varsize;\
|
|
memcpy(optval, varname, *optlen);\
|
|
}\
|
|
else *optlen = 0;\
|
|
DebugExitINT(WssaGetSocketOption, 0); \
|
|
return 0;
|
|
|
|
#define RG_SOCKOPT_GET(optname, varname, varsize)\
|
|
case optname :\
|
|
TRACE_OUT( #optname ); \
|
|
if (ssi){\
|
|
if (*optlen < varsize){\
|
|
*optlen = varsize;\
|
|
DebugExitINT(WssaGetSocketOption, WSAEFAULT); \
|
|
return WSAEFAULT;\
|
|
}\
|
|
*optlen = varsize;\
|
|
memcpy(optval, varname, *optlen);\
|
|
}\
|
|
else *optlen = 0;\
|
|
DebugExitINT(WssaGetSocketOption, 0); \
|
|
return 0;
|
|
|
|
int WSSAFNCT WssaGetSocketOption(SECURE_SOCKET ss, int level, int optname, char FAR * optval, int FAR *optlen)
|
|
{
|
|
VAR_SSI(ssi,ss);
|
|
int retval;
|
|
|
|
DebugEntry(WssaGetSocketOption);
|
|
|
|
/*Is this a new option category?*/
|
|
if (SO_SSL_LEVEL == level)
|
|
{
|
|
// if (NULL == ssi) ssi = ConstructSSI(ss);
|
|
switch (optname){
|
|
DWORD_SOCKOPT_GET(SO_SSL_FLAGS, ssi->dwSSLUserFlags);
|
|
DWORD_SOCKOPT_GET(SO_SSL_CERTIFICATE_TYPE, ssi->nCertificateType);
|
|
PC_SOCKOPT_GET( SO_SSL_CERTIFICATE, ssi->pCertificateData, ssi->nCertificateSize);
|
|
PC_SOCKOPT_GET( SO_SSL_SESSION_ID_DATA, ssi->rgSessionIdData, ssi->nSessionIdSize);
|
|
PC_SOCKOPT_GET( SO_SSL_CIPHER_SPECS, ssi->pCipherSpecData, ssi->nCipherSpecSize);
|
|
RG_SOCKOPT_GET( SO_SSL_STATE_INFO, &ssi->nSessionIdSize , sizeof(ssi->rgSessionIdData) + sizeof(ssi->rgMaster) + sizeof(int) + sizeof(ssi->pCipherInfo) + 10 /*fudge factor*/);
|
|
}
|
|
}
|
|
/*drop down to base case*/
|
|
retval= getsockopt(SS2S(ss),level,optname,optval,optlen);
|
|
|
|
DebugExitINT(WssaGetSocketOption, retval);
|
|
return(retval);
|
|
}
|
|
|
|
#undef DWORD_SOCKOPT_GET
|
|
#undef PC_SOCKOPT_GET
|
|
|
|
#ifndef BETTER_RANDOM
|
|
static void SeedRandomNumber()
|
|
{
|
|
unsigned int seed = 0;
|
|
POINT point;
|
|
LARGE_INTEGER li;
|
|
|
|
if ( QueryPerformanceCounter( &li ) )
|
|
seed += li.LowPart + li.HighPart;
|
|
|
|
seed += GetCurrentTime();
|
|
|
|
seed += ((seed * 0x7F3D726F) + ((unsigned int) GetCurrentProcess()));
|
|
seed += ((seed * 0xF35) + ((unsigned int) GetCurrentProcessId()));
|
|
seed += ((seed * 0xC9) + ((unsigned int) GetCurrentThread()));
|
|
seed += ((seed * 0xF) + ((unsigned int) GetCurrentThreadId()));
|
|
if ( GetCursorPos( &point ) )
|
|
seed += (point.x * point.y);
|
|
|
|
seed += GetCurrentTime();
|
|
|
|
srand( seed );
|
|
}
|
|
#endif
|
|
|
|
/*To put in blocking stuff. Just in case we ever go threaded---------------*/
|
|
int WSSAFNCT WssaStartup (WORD wVersionRequired, LPWSADATA lpWSAData)
|
|
{
|
|
int errno;
|
|
|
|
DebugEntry(WssaStartup);
|
|
|
|
#ifndef BETTER_RANDOM
|
|
SeedRandomNumber();
|
|
#endif
|
|
errno = WSAStartup (wVersionRequired, lpWSAData);
|
|
if (0==errno) WssaTableStartup();
|
|
|
|
DebugExitINT(WssaStartup, errno);
|
|
return errno;
|
|
}
|
|
|
|
int WSSAFNCT WssaCleanup (void)
|
|
{
|
|
int retval;
|
|
|
|
DebugEntry(WssaCleanup);
|
|
|
|
WssaTableShutdown();
|
|
retval= WSACleanup();
|
|
|
|
DebugExitINT(WssaCleanup, retval);
|
|
return(retval);
|
|
}
|
|
|
|
|