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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user