Adding poll impl to native ssl. Also adding debug messagebox's to track down connect failures on some devices

git-svn-id: svn://10.0.0.236/trunk@189372 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
dougt%meer.net
2006-02-07 23:47:04 +00:00
parent dcf5ed5a48
commit 09bef7a755

View File

@@ -30,6 +30,21 @@ static SSL_CRACK_CERTIFICATE_FN gSslCrackCertificate = 0 ;
static SSL_FREE_CERTIFICATE_FN gSslFreeCertificate = 0 ;
static HINSTANCE gSchannel = NULL ;
static PRDescIdentity nsWINCESSLIOLayerIdentity;
static PRIOMethods nsWINCESSLIOLayerMethods;
void MessageBoxWSAError(const char * msg)
{
char buffer[100];
int error = WSAGetLastError();
if (error == 0)
return;
sprintf(buffer, "%s error is: %d", msg, error);
MessageBox(0, buffer, buffer, MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND);
}
class nsWINCESSLSocketProvider : public nsISocketProvider
{
public:
@@ -55,13 +70,16 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSITRANSPORTSECURITYINFO
void Init(const char *destinationHost, const char *proxyHost, PRInt32 proxyPort)
nsresult Init(const char *destinationHost, const char *proxyHost, PRInt32 proxyPort)
{
mDestinationHost = destinationHost;
mProxyHost = proxyHost;
mProxyPort = proxyPort;
return NS_OK;
};
SOCKET mSocket;
nsCString mDestinationHost;
nsCString mProxyHost;
PRInt32 mProxyPort;
@@ -144,7 +162,10 @@ static int SSLValidationHook(DWORD dwType, LPVOID pvArg, DWORD dwChainLen, LPBLO
}
if (!gSslCrackCertificate || !gSslFreeCertificate)
{
MessageBox(0, "Could not find the right stuff in the default security library", "schannel.dll", MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND);
return SSL_ERR_BAD_DATA;
}
}
X509Certificate * cert = 0;
@@ -204,6 +225,158 @@ static int SSLValidationHook(DWORD dwType, LPVOID pvArg, DWORD dwChainLen, LPBLO
return res;
}
struct sockaddr *
nspr2winsock(const PRNetAddr *addr, int *len)
{
struct sockaddr_in *ws = (struct sockaddr_in*) malloc(sizeof(*ws));
if (!ws)
return NULL;
memset(ws, 0, sizeof(*ws));
// family
ws->sin_family = AF_INET;
// ip
memcpy(&ws->sin_addr, &addr->inet.ip, sizeof(ws->sin_addr));
// port
ws->sin_port = addr->inet.port;
*len = sizeof(*ws);
return (struct sockaddr *)ws;
}
static PRStatus PR_CALLBACK
nsWINCESSLIOLayerConnect(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime /*timeout*/)
{
nsWINCESSLSocketInfo * info = (nsWINCESSLSocketInfo*) fd->secret;
if (info == NULL)
return PR_FAILURE;
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (!s)
{
MessageBox(0, "Failed to create a socket", "connect()", MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND);
return PR_FAILURE;
}
info->mSocket = s;
// set the socket to secure mode
DWORD dwFlag = SO_SEC_SSL ;
DWORD error = setsockopt (s, SOL_SOCKET, SO_SECURE, (char *)&dwFlag, sizeof(dwFlag));
if (error != 0)
{
MessageBox(0, "Failed to setsockopt", "connect()", MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND);
return PR_FAILURE;
}
// set the certificate validation callback.
SSLVALIDATECERTHOOK sslHook ;
sslHook.HookFunc = SSLValidationHook;
NS_ADDREF(info);
sslHook.pvArg = (void *) info; // XXXX Leak! what is the lifespan of this?
if ( WSAIoctl (s,
SO_SSL_SET_VALIDATE_CERT_HOOK,
&sslHook,
sizeof sslHook,
NULL,
0,
NULL,
NULL,
NULL) )
{
MessageBox(0, "SO_SSL_SET_VALIDATE_CERT_HOOK", "connect()", MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND);
return PR_FAILURE;
}
int len;
struct sockaddr* ws = nspr2winsock(addr, &len);
if (!ws)
return PR_FAILURE;
int result = connect(s, ws, len);
if (result == 0)
return PR_SUCCESS;
MessageBoxWSAError("connect()");
return PR_FAILURE;
}
static PRStatus PR_CALLBACK
nsWINCESSLIOLayerClose(PRFileDesc *fd)
{
nsWINCESSLSocketInfo * info = (nsWINCESSLSocketInfo*) fd->secret;
PRDescIdentity id = PR_GetLayersIdentity(fd);
if (info && id == nsWINCESSLIOLayerIdentity)
{
NS_RELEASE(info);
fd->identity = PR_INVALID_IO_LAYER;
}
// closesocket(info->mSocket);
// NS_RELEASE(info);
// fd->secret = nsnull;
return PR_SUCCESS;
}
static PRInt32 PR_CALLBACK
nsWINCESSLIOLayerAvailable(PRFileDesc *fd)
{
MessageBox(0, "available.", "available.", MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND);
return 1;
}
static PRInt32 PR_CALLBACK
nsWINCESSLIOLayerRead(PRFileDesc* fd, void* buf, PRInt32 amount)
{
nsWINCESSLSocketInfo * info = (nsWINCESSLSocketInfo*) fd->secret;
if (info == NULL)
return PR_OUT_OF_MEMORY_ERROR;
WSASetLastError (0) ;
PRInt32 rv = recv(info->mSocket, (char*)buf, amount, 0);
MessageBoxWSAError("read");
return rv;
}
static PRInt32 PR_CALLBACK
nsWINCESSLIOLayerWrite(PRFileDesc* fd, const void* buf, PRInt32 amount)
{
nsWINCESSLSocketInfo * info = (nsWINCESSLSocketInfo*) fd->secret;
if (info == NULL)
return PR_OUT_OF_MEMORY_ERROR;
WSASetLastError (0) ;
PRInt32 rv = send(info->mSocket, (char*)buf, amount, 0);
MessageBoxWSAError("write");
return rv;
}
static PRInt16 PR_CALLBACK nsWINCESSLIOLayerPoll(PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
{
nsWINCESSLSocketInfo * info = (nsWINCESSLSocketInfo*) fd->secret;
if (info == NULL)
return PR_OUT_OF_MEMORY_ERROR;
*out_flags = PR_POLL_READ | PR_POLL_WRITE | PR_POLL_EXCEPT;
return 1;
}
NS_IMPL_THREADSAFE_ISUPPORTS1(nsWINCESSLSocketProvider, nsISocketProvider)
NS_IMETHODIMP
@@ -216,48 +389,56 @@ nsWINCESSLSocketProvider::NewSocket(PRInt32 family,
PRFileDesc **result,
nsISupports **socksInfo)
{
SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (!s)
return NS_ERROR_SOCKET_CREATE_FAILED;
static PRBool firstTime = PR_TRUE;
if (firstTime) {
nsWINCESSLIOLayerIdentity = PR_GetUniqueIdentity("WINCESSL layer");
nsWINCESSLIOLayerMethods = *PR_GetDefaultIOMethods();
nsWINCESSLIOLayerMethods.connect = nsWINCESSLIOLayerConnect;
nsWINCESSLIOLayerMethods.close = nsWINCESSLIOLayerClose;
nsWINCESSLIOLayerMethods.available = nsWINCESSLIOLayerAvailable;
nsWINCESSLIOLayerMethods.write = nsWINCESSLIOLayerWrite;
nsWINCESSLIOLayerMethods.read = nsWINCESSLIOLayerRead;
nsWINCESSLIOLayerMethods.poll = nsWINCESSLIOLayerPoll;
firstTime = PR_FALSE;
}
PRFileDesc *fd = PR_OpenTCPSocket(family);
if (!fd)
return NS_ERROR_OUT_OF_MEMORY;
PRFileDesc * layer;
PRStatus rv;
layer = PR_CreateIOLayerStub(nsWINCESSLIOLayerIdentity, &nsWINCESSLIOLayerMethods);
if (! layer)
return NS_ERROR_UNEXPECTED;
nsWINCESSLSocketInfo * infoObject = new nsWINCESSLSocketInfo();
if (!infoObject)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(infoObject);
layer->secret = (PRFilePrivate*) infoObject;
rv = PR_PushIOLayer(fd, PR_GetLayersIdentity(fd), layer);
if (NS_FAILED(rv))
return NS_ERROR_UNEXPECTED;
nsresult initrv = infoObject->Init(host, proxyHost, proxyPort);
if (NS_FAILED(initrv))
{
closesocket(s);
MessageBox(0, "Can not create ssl socket.", "Can not create ssl socket.", MB_APPLMODAL | MB_TOPMOST | MB_SETFOREGROUND);
return NS_ERROR_FAILURE;
}
NS_ADDREF(infoObject);
infoObject->Init(host, proxyHost, proxyPort);
// set the socket to secure mode
DWORD dwFlag = SO_SEC_SSL ;
if ( setsockopt (s, SOL_SOCKET, SO_SECURE, (char *)&dwFlag, sizeof(dwFlag)) )
goto loser;
// set the certificate validation callback.
SSLVALIDATECERTHOOK sslHook ;
sslHook.HookFunc = SSLValidationHook;
NS_ADDREF(infoObject);
sslHook.pvArg = (void *) infoObject; // XXXX Leak! what is the lifespan of this?
if ( WSAIoctl (s, SO_SSL_SET_VALIDATE_CERT_HOOK, &sslHook, sizeof sslHook, NULL, 0, NULL, NULL, NULL) )
goto loser;
*result = PR_ImportTCPSocket(s);
if (!*result)
goto loser;
*result = fd;
*socksInfo = (nsISupports*) (nsITransportSecurityInfo*) infoObject;
return NS_OK;
loser:
closesocket(s);
NS_RELEASE(infoObject);
return NS_ERROR_SOCKET_CREATE_FAILED;
}
NS_IMETHODIMP